Series de Fourier (MAMBD)
| Trabajo realizado por estudiantes | |
|---|---|
| Título | Series de Fourier. Grupo MAMBD |
| Asignatura | EDP |
| Curso | 2024-25 |
| Autores | Matilde Rubio Arranz, Antonio Lozano Fernández, Marcos Gil García, Bárbara Jiménez Pérez y Daniel Marcos Viña |
| Este artículo ha sido escrito por estudiantes como parte de su evaluación en la asignatura | |
1 Introducción
El interés de las series de Fourier radica en su capacidad para aproximar, a partir de una base de funciones trigonométricas, aplicaciones periódicas ampliando así el alcance de los desarrollos de Taylor. Sea [math]f[/math] una función integrable y periódica en [math][-T,T][/math], dada la base
[math]\mathcal{B}=\left\{ \frac{1}{\sqrt{2T}} \right\} \cup
\left\{ \frac{1}{\sqrt{T}} \cdot \cos \left( \frac{n\pi x}{T} \right) \right\}_{n \in \mathbb{N}}
\cup
\left\{ \frac{1}{\sqrt{T}} \cdot \sin \left( \frac{n\pi x}{T} \right) \right\}_{n \in \mathbb{N}},[/math]
su serie de Fourier viene dada por la expresión:
[math]\begin{equation*}
f(x) \sim \frac{d_0}{\sqrt{2T}} + \sum_{n=1}^{\infty} d_n \cdot\frac{1}{\sqrt{T}} \cos \left( \frac{n\pi x}{T} \right) + \sum_{n=1}^{\infty} c_n \cdot \frac{1}{\sqrt{T}}\sin \left( \frac{n\pi x}{T} \right)
\end{equation*}[/math]
cuyos coeficientes son:
[math]
\begin{aligned}
&\bullet \quad d_0 = \langle f, \frac{1}{\sqrt{2T}} \rangle = \int_{-T}^{T} f(x) \cdot \frac{1}{\sqrt{2T}} \,dx \\
&\bullet \quad d_n = \langle f, \frac{1}{\sqrt{T}}\cos \left( \frac{n\pi x}{T} \right) \rangle = \frac{1}{\sqrt{T}}\int_{-T}^{T} f(x) \cdot \cos \left( \frac{n\pi x}{T} \right) \,dx \\
&\bullet \quad c_n = \langle f, \frac{1}{\sqrt{T}}\sin \left( \frac{n\pi x}{T} \right) \rangle = \frac{1}{\sqrt{T}}\int_{-T}^{T} f(x) \cdot \sin \left( \frac{n\pi x}{T} \right) \,dx.
\end{aligned}
[/math]
2 Aproximación de una función continua
Para ilustrar la aproximación por series trigonométricas, consideramos la función [math]f(x)=1-2\left|\frac{1}{2}-x\right|[/math] en el intervalo [math][0,1][/math]. Buscamos extenderla de forma impar obteniendo una función
[math]g(x)=\left\{\begin{array}{cc} f(x), & x\in[0,1] \\ -f(-x), & x\in[-1,0) \end{array}\right..[/math]
La extensión impar que buscamos viene dada por [math]g(x)=\left\{\begin{array}{cc} -2-2x, & -1\leq x\lt-\frac{1}{2} \\ 2x, & -\frac{1}{2}\leq x\lt\frac{1}{2} \\ 2-2x, & \frac{1}{2}\leq x\leq1 \end{array}\right.,[/math] que es continua en [math][-1,1][/math].
Ahora, por ser [math]f\in L^2([-1,1])[/math], utilizamos para la aproximación la base trigonométrica correspondiente [math]\left\{\frac{1}{\sqrt{2}}, \cos(n\pi x), \sin(n\pi x)\right\}_{n\in\mathbb{N}}[/math]. Sin embargo, al haber extendido la función de forma impar, el producto escalar de [math]f[/math] con las funciones pares de la base resulta ser impar. Con esto deducimos que integrar dicho producto en un intervalo simétrico da como resultado cero, pues las áreas positivas y negativas se anulan entre sí debido a la simetría de la función con respecto al origen. Entonces podemos definir [math]f_n(x)[/math] como la suma de los primeros [math]n[/math] términos de la serie de Fourier
Tras el análisis anterior, veamos gráficamente como, según aumentamos la cantidad de términos de la serie, esta se aproxima mejor a la función original [math]f[/math]. En los siguientes gráficos observamos como, efectivamente, al aumentar la [math]n[/math], los primeros términos de la serie de Fourier se van acercando a nuestra función original. Así mismo, gracias a esta mejora en la aproximación, en la segunda gráfica podemos apreciar como el error disminuye conforme aumenta [math]n[/math]. Destacamos que el error de aproximación desciende del orden [math]10^{-2}[/math], que es una cifra más que aceptable teniendo en cuenta que solamente hemos tomado 20 términos de una serie infinita.
import numpy as np
import matplotlib.pyplot as plt
#Primero, hemos definido la función del enunciado y su extensión impar. A continuación de eso, hemos creado dos funciones, las cuales crean los coeficientes de Fourier y la serie de Fourier, respectivamente. Además, se ha creado una última función para los errores. Usando matplotlib.pyplot, deja las siguientes gráficas:
# Definimos la función del enunciado con la que trabajar
def f(x):
return 1 - 2 * np.abs(1/2 - x)
# Extensión impar de la propia función para poder aproximarla con la serie de Fourier
def odd_extension(x):
return np.where(x < 0, -f(-x), f(x))
# Cálculo de los coeficientes de la serie con integración numérica por medio del método del trapecio
def compute_coefficients(n_max, dx=1e-3):
x = np.arange(0, 1, dx)
a_k = []
for k in range(1, n_max + 1):
integrand = f(x) * np.sin(k * np.pi * x)
a_k.append(2 * np.trapz(integrand, x)) # Integral numérica por trapecios
return a_k
# Construcción de la serie de Fourier
def fourier_approximation(x, a_k):
f_n = np.zeros_like(x)
for k, ak in enumerate(a_k, start=1):
f_n += ak * np.sin(k * np.pi * x)
return f_n
# Valores de n
n_values = [1, 5, 10]
# Discretización del intervalo
x = np.linspace(0, 1, 1000)
x_ext = np.linspace(-1, 1, 2000)
# Gráfica de la función original
plt.plot(x, f(x), label='f(x)', color='black', linewidth=2)
# Aproximaciones de Fourier con f extendida
for n in n_values:
a_k = compute_coefficients(n)
f_n = fourier_approximation(x_ext, a_k)
plt.plot(x_ext, f_n, label=f'n={n}')
plt.legend()
plt.xlabel('x')
plt.ylabel('f(x) y f_n(x)')
plt.title('Comparación de la extensión impar con la Aproximación de Fourier')
plt.show()
# Calculamos el error de estimación entre la correspondiente f_n(x) y f(x)
def compute_errors(n_values, x, dx=1e-3):
L2_errors = []
uniform_errors = []
f_exact = odd_extension(x)
for n in n_values:
a_k = compute_coefficients(n, dx)
f_n = fourier_approximation(x, a_k)
error = np.abs(f_exact - f_n)
L2_error = np.sqrt(np.trapz(error**2, x)) # Norma L^2
uniform_error = np.max(error) # Norma uniforme
L2_errors.append(L2_error)
uniform_errors.append(uniform_error)
return L2_errors, uniform_errors
# Valores de n
n_values2 = np.arange(1, 21)
# Discretización del intervalo
x_ext = np.linspace(-1, 1, 2000)
# Cálculo de errores
L2_errors, uniform_errors = compute_errors(n_values2, x_ext)
# Gráfica de errores
plt.figure(figsize=(8, 5))
plt.plot(n_values2, L2_errors, label='Error L2', marker='o')
plt.plot(n_values2, uniform_errors, label='Error Uniforme', marker='s')
plt.yscale('log')
plt.xlabel('Número de términos n')
plt.ylabel('Error')
plt.title('Errores en función de n')
plt.legend()
plt.grid()
plt.show()3 Cambio de intervalo de aproximación
A continuación aproximaremos la función \( f(x) = x e^x \) en el intervalo \([-2, 3]\) mediante su serie de Fourier. En primer lugar, calcularemos la base trigonométrica asociada al espacio \( L^2([-2, 3]) \). Definimos el espacio [math]L^2(-T, T)[/math] como el conjunto de funciones medibles [math]f(x)[/math] en el intervalo [math][-T, T][/math] tales que:[math] \int_{-T}^{T} |f(x)|^2 \, dx \lt \infty [/math]. Como ya sabemos, en el espacio [math]L^2([-\pi, \pi])[/math] la base trigonométrica asociada es:
En general, para [math]L^2([a,b])[/math], mediante el cambio de variable [math]
g(x) = \frac{2\pi}{b - a} (x - a) - \pi,
[/math] se tiene que la base trigonométrica asociada es
que es una base ortonormal para [math]L^2([a,b])[/math]. Bajo este cambio de variable, una función [math]f(x)[/math] en [math]L^2([a,b])[/math] se puede expresar como:
donde [math]g(x)[/math] es el cambio de variable aplicado, y [math]d_n[/math] y [math]c_n[/math] son los coeficientes correspondientes. Así, [math]g(x) \in [-\pi, \pi][/math], permitiendo trasladar la base ortonormal del espacio [math]L^2(-\pi, \pi)[/math] al nuevo intervalo [math][a, b][/math].
Ahora, analicemos nuestro caso concreto, el intervalo [math][-2, 3][/math]. Obtenemos que:
- Decimos que una función [math]f(x)[/math] satisface la condición de dirichlet si [math]f(x) \in L^2([-T,T])[/math] es continua salvo en un conjunto finito de puntos y podemos dividir [math][-T,T][/math] en un conjunto de subintervalos en los que [math]f[/math] es monótona.
- Teorema: Sea [math]f \in L^2([-2, 3])[/math] una función continua y que satisface la condición de Dirichlet, entonces su serie de Fourier converge puntualmente a [math]f(x)[/math] si [math]x[/math] es un punto de continuidad en [math][-2,3][/math].
Claramente, [math]f(x)[/math] es continua y satisface la condición de dirichlet. Además, se verifica que [math]f(x) \in L^2([-2, 3])[/math], pues:
Concluimos con que su desarrollo en serie de Fourier converge en los puntos de continuidad a [math]f(x)[/math]. Finalmente, calculemos los coeficientes de Fourier. Para la base ortonormal asociada al espacio [math]L^2([-2, 3])[/math], los coeficientes de Fourier de [math]f(x)[/math] son:
[math] d_n = \frac{\sqrt{2}}{\sqrt{5}c} \int_{-2}^{3} x e^x \cos\left( n \frac{2\pi x - \pi}{5} \right) \, dx \quad \text{para} \quad n \geq 1 [/math]
[math] c_n = \frac{\sqrt{2}}{\sqrt{5}} \int_{-2}^{3} x e^x \sin\left( n \frac{2\pi x - \pi}{5} \right) \, dx \quad \text{para} \quad n \geq 1. [/math]
Calcularemos los coeficientes [math]d_n[/math] y [math]c_n[/math] mediante métodos numéricos en Python, obteniendo así la serie de Fourier de [math]f(x)[/math] en [math][-2,3][/math] y, por tanto, la gráfica de la función y de la serie para sus primeros [math]5, 10[/math] y [math]20[/math] términos.
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import quad
# Definimos la función f(x)
def f(x):
return x * np.exp(-x)
# Intervalo de definición
a= -2
b = 3
# Funciones base ortonormales en L^2([-2,3])
def phi0(x):
return 1/np.sqrt(5)
def phi(n, x):
return np.sqrt(2/5) * np.cos(n * (2*np.pi*x - np.pi) / 5)
def psi(n, x):
return np.sqrt(2/5) * np.sin(n * (2*np.pi*x - np.pi) / 5)
# Cálculo de los coeficientes de Fourier
d0, _ = quad(lambda x: f(x) * phi0(x), a, b)
# Se calcularán los coeficientes para n=1,...,N_max
N_max = 20
d_coeffs = [] # para los coeficientes asociados a los cosenos
c_coeffs = [] # para los coeficientes asociados a los senos
for n in range(1, N_max+1):
d_n, _ = quad(lambda x: f(x) * phi(n, x), a, b)
c_n, _ = quad(lambda x: f(x) * psi(n, x), a, b)
d_coeffs.append(d_n)
c_coeffs.append(c_n)
# Función que reconstruye la serie de Fourier truncada a N términos
def fourier_series(x, N):
s = d0 * phi0(x)
for n in range(1, N+1):
s += d_coeffs[n-1] * phi(n, x) + c_coeffs[n-1] * psi(n, x)
return s
x_vals = np.linspace(a, b, 400)
f_vals = f(x_vals)
# Lista de números de términos para la aproximación
n_list = [5, 10, 20]
# Se generan tres gráficos, uno para cada valor de n
plt.figure(figsize=(15, 4))
for i, n in enumerate(n_list, 1):
# Se evalúa la serie de Fourier para cada x
s_vals = np.array([fourier_series(x, n) for x in x_vals])
plt.subplot(1, 3, i)
plt.plot(x_vals, f_vals, label=r'$f(x)= x e^-x$', color='blue', linestyle='--')
plt.plot(x_vals, s_vals, label=f'Aproximación (n={n})', color='red')
plt.title(f'Aproximación de Fourier con n = {n} términos')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()