Series de Fourier (Grupo PPAD)
| Trabajo realizado por estudiantes | |
|---|---|
| Título | Series de Fourier (Grupo PPAD). |
| Asignatura | EDP |
| Curso | 2024-25 |
| Autores | Pablo Vidal Nacle, Pablo Maestro Fernández, Alex Heredero Santamaría, Diego Moñino Vizmanos |
| Este artículo ha sido escrito por estudiantes como parte de su evaluación en la asignatura | |
Contenido
1 . Introducción
Se define el espacio de Hilbert [math]L^2(a,b)[/math] como:
donde [math] a,b \in \mathbb{R} [/math] y [math] a \lt b [/math]. [math]L^2(a,b)[/math] es un espacio vectorial con producto escalar asociado:
Esta construcción del espacio [math] L^{2} [/math] motiva plantear la posibilidad de definir una base numerable que permita expresar todos los elementos del espacio en función de los elementos de la base.
2 . Base trigonométrica
Tal y como se ha definido en la introducción, consideramos el espacio [math]L^2(-\pi,\pi)[/math]. En éste se define la base numerable [math] \beta [/math] dada por los siguientes elementos:
que se conoce como referencia de Fourier trigonométrica.
import numpy as np
import matplotlib.pyplot as plt
# Definir el rango de x
x = np.linspace(-1, 1, 400)
# Graficar el primer término de la base (constante 1/2)
plt.plot(x, np.full_like(x, 1/2), label=r'$\frac{1}{2}$', linewidth=2)
# Graficar los términos cos(nπx) y sin(nπx) para n = 1, ..., 10
for n in range(1, 11):
plt.plot(x, np.cos(n * np.pi * x), label=fr'$\cos({n}\pi x)$')
plt.plot(x, np.sin(n * np.pi * x), label=fr'$\sin({n}\pi x)$')
# Configurar la gráfica
plt.axhline(0, color='black', linewidth=0.8)
plt.axvline(0, color='black', linewidth=0.8)
plt.legend(loc='upper right', fontsize='x-small', ncol=2)
plt.xlabel('x')
plt.ylabel('Valor de la función')
plt.title('Primeros 10 términos de la base trigonométrica')
plt.grid(True, linestyle='--', alpha=0.6)
plt.show()import numpy as np
import matplotlib.pyplot as plt
# Definir el rango de x
x = np.linspace(-1, 1, 400)
# Crear una figura con 3 subgráficos
fig, axes = plt.subplots(3, 1, figsize=(6, 12))
# Graficar el primer término de la base (constante 1/2)
axes[0].plot(x, np.full_like(x, 1/2), label=r'$\frac{1}{2}$', linewidth=2)
axes[0].set_title('Término constante')
axes[0].grid(True, linestyle='--', alpha=0.6)
axes[0].legend()
# Graficar los términos cos(nπx) para n = 1, ..., 10
for n in range(1, 11):
axes[1].plot(x, np.cos(n * np.pi * x), label=fr'$\cos({n}\pi x)$', linewidth=2)
axes[1].set_title('Funciones coseno')
axes[1].grid(True, linestyle='--', alpha=0.6)
axes[1].legend(fontsize='x-small', ncol=2)
# Graficar los términos sin(nπx) para n = 1, ..., 10
for n in range(1, 11):
axes[2].plot(x, np.sin(n * np.pi * x), label=fr'$\sin({n}\pi x)$', linewidth=2)
axes[2].set_title('Funciones seno')
axes[2].grid(True, linestyle='--', alpha=0.6)
axes[2].legend(fontsize='x-small', ncol=2)
# Ajustar diseño
plt.tight_layout()
plt.show()3 . Aproximación de una función por la base trigonométrica
Seadefinida en el intervalo [-2,3], se busca aproximar f mediante la base trigonométrica del espacio [math]L^2(-2,3)[/math].
Consideramos el espacio de Hilbert \( L^2(- \pi, \pi) \) con el producto interno \( \langle \cdot, \cdot \rangle_{L^2} \). En este espacio tomamos la base de Fourier trigonométrica:
Si consideramos ahora el espacio \( L^2(a, b) \), buscamos una base ortonormal (referencia de Fourier) en este espacio. Para ello, hacemos el cambio de variable:
De esta manera, \( h(x) \in [-\pi, \pi] \), lo que permite trasladar la base ortonormal del espacio \( L^2(- \pi, \pi) \) al nuevo intervalo \( [a, b] \).
De esta forma, obtenemos la base de Fourier de \( L^2(a,b) \):
Para preservar la ortonormalidad en \( L^2(a,b) \), los senos y cosenos han sido normalizados con el factor:
para los términos trigonométricos.
Una función f\in\( L^2(a,b) \) puede escribirse entonces:
En [math] L^2(-2,3) [/math], nos queda la base:
Sea la función \( f(x) = x e^{-x} \). Se verifica que \( f(x) \in L^2(-2,3) \), pues:
Dado que \( f(x) \) es continua y satisface la condición de Dirichlet, su desarrollo en serie de Fourier converge a la función en los puntos de continuidad y en los extremos. Así, se tiene:
Calculemos ahora los coeficientes de la serie de Fourier
El coeficiente \( d_0 \) se obtiene como:
Para los coeficientes \( d_n \):
Para los coeficientes \( d_m \):
De esta forma, se puede aproximar la función f mediante los primeros 5, 10 y 20 términos de su desarrollo en serie de Fourier, empleando el siguiente código de python:
from tqdm import tqdm
import sympy as sp
import math
import numpy as np
import matplotlib.pyplot as plt
n=10
def calcular_aproximacion_fourier(n):
e = 0
l = 0
x = sp.symbols('x')
for i in tqdm(range(1, n)):
integrand = (math.sqrt(2)/math.sqrt(5)) * x
* sp.exp(-x) * sp.cos(i * ((2*sp.pi*x - sp.pi) / 5))
integral_result = sp.integrate(integrand, (x, -2, 3))
integrand2 = (math.sqrt(2)/math.sqrt(5)) * x
* sp.exp(-x) * sp.sin(i * ((2*sp.pi*x - sp.pi) / 5))
integral_result2 = sp.integrate(integrand2, (x, -2, 3))
e += integral_result * (math.sqrt(2)/math.sqrt(5)) *
sp.cos(i * ((2*sp.pi*x - sp.pi) / 5))
l += integral_result2 * (math.sqrt(2)/math.sqrt(5)) *
sp.sin(i * ((2*sp.pi*x - sp.pi) / 5))
d0 = -(4 + sp.exp(5)) / (math.sqrt(5) * sp.exp(3))
f = d0 / math.sqrt(5) + e + l
return sp.lambdify(x, f, "numpy")
# Definir la función f(x) = x * exp(-x)
def f(x):
return x * np.exp(-x)
# Generar valores de x en el rango [-2, 3]
x_vals = np.linspace(-2, 3, 1000)
y_vals = f(x_vals)
f_numeric=calcular_aproximacion_fourier(n)
# Aproximación de Fourier (f_numeric debe estar definida previamente)
y_fourier = f_numeric(x_vals)
# Calcular el error
error_vals = np.abs(y_vals - y_fourier)
# Crear el gráfico de la función y su aproximación
plt.figure(figsize=(6,4))
plt.plot(x_vals, y_vals, label=r'$f(x) = x e^{-x}$',linestyle='dashed', color='b')
plt.plot(x_vals, y_fourier, label=f"Aproximación n={n}", color='r')
plt.axhline(0, color='black', linewidth=0.5)
plt.axvline(0, color='black', linewidth=0.5)
plt.xlabel("x")
plt.ylabel("f(x)")
plt.title("Comparación entre f(x) y su Aproximación de Fourier")
plt.legend()
plt.grid()
plt.show()
# Gráfico del error
plt.figure(figsize=(6,4))
plt.plot(x_vals, error_vals, label="Error Absoluto", color='g')
plt.xlabel("x")
plt.ylabel("Error")
plt.title("Error entre f(x) y su aproximación de Fourier")
plt.legend()
plt.grid()
plt.show
# Valores de n a evaluar
n_vals1 = np.linspace(10,200,20)
n_vals=[]
for i in range(20):
n_vals.append(int(n_vals1[i]))
error_L2_vals=[]
error_supremo_vals = []
for i in n_vals:
f_numeric = calcular_aproximacion_fourier(i)
y_fourier = f_numeric(x_vals)
error_L2 = np.sqrt(np.trapz(np.abs(y_vals - y_fourier)**2, x_vals))
error_L2_vals.append(error_L2)
error_supremo = np.sqrt(np.trapz(np.abs(y_vals - y_fourier)**2, x_vals))
error_supremo_vals.append(error_supremo)
# Graficar el error en norma L2 vs n
plt.figure(figsize=(6, 4))
plt.plot(n_vals, error_L2_vals, linestyle='-', color='r')
plt.xlabel("n")
plt.ylabel("Error L2")
plt.title("Error en Norma L2 para distintos valores de n")
plt.legend()
plt.grid()
plt.show()
# Graficar el error en norma supremo vs n
plt.figure(figsize=(6, 4))
plt.plot(n_vals, error_supremo_vals, linestyle='-', color='r')
plt.xlabel("n")
plt.ylabel("Error norma supremo")
plt.title("Error en Norma supremo para distintos valores de n")
plt.legend()
plt.grid()
plt.show()
4 . Referencias
- Sandro Salsa, Gianmaria Verzini. Partial Differential Equations in Action(Edición 4).






