Diferencia entre revisiones de «Series de Fourier (Grupo ILIA)»

De MateWiki
Saltar a: navegación, buscar
Línea 171: Línea 171:
 
from scipy.integrate import quad
 
from scipy.integrate import quad
  
# Definir la función f(x)
+
# Intervalo
 +
a, b = -2, 3
 +
L = (b - a) / 2  # Semi-longitud del intervalo
 +
 
 +
# Función a aproximar
 
def f(x):
 
def f(x):
 
     return x * np.exp(-x)
 
     return x * np.exp(-x)
  
# Definir los límites del intervalo
+
# Coeficiente a_0
a, b = -2, 3
+
def a_0():
L = (b - a) / 2  # Semilongitud del intervalo
+
     return (1 / L) * quad(lambda x: f(x), a, b)[0]
 
+
# Base trigonométrica en [-2,3]
+
def phi_0(x):
+
     return 1 / np.sqrt(b - a)
+
 
+
def phi_cos(n, x):
+
    return np.cos(n * np.pi * (x - a) / (b - a))
+
 
+
def phi_sin(n, x):
+
    return np.sin(n * np.pi * (x - a) / (b - a))
+
 
+
# Cálculo de coeficientes de Fourier
+
def coeficiente_an(n):
+
    result, _ = quad(lambda x: f(x) * phi_cos(n, x), a, b)
+
    return result / np.sqrt(b - a)
+
  
def coeficiente_bn(n):
+
# Coeficientes a_n y b_n
     result, _ = quad(lambda x: f(x) * phi_sin(n, x), a, b)
+
def a_n(n):
    return result / np.sqrt(b - a)
+
     return (1 / L) * quad(lambda x: f(x) * np.cos(n * np.pi * (x - a) / L), a, b)[0]
  
def coeficiente_a0():
+
def b_n(n):
     result, _ = quad(lambda x: f(x) * phi_0(x), a, b)
+
     return (1 / L) * quad(lambda x: f(x) * np.sin(n * np.pi * (x - a) / L), a, b)[0]
    return result / np.sqrt(b - a)
+
  
# Aproximación de la serie de Fourier
+
# Aproximación de Fourier con N términos
def aproximacion_fourier(x, N):
+
def fourier_aprox(x, N):
     suma = coeficiente_a0() * phi_0(x)
+
     suma = a_0() / 2
 
     for n in range(1, N + 1):
 
     for n in range(1, N + 1):
         suma += coeficiente_an(n) * phi_cos(n, x) + coeficiente_bn(n) * phi_sin(n, x)
+
         suma += a_n(n) * np.cos(n * np.pi * (x - a) / L) + b_n(n) * np.sin(n * np.pi * (x - a) / L)
 
     return suma
 
     return suma
  
# Valores de x para graficar
+
# Valores de N a considerar
X = np.linspace(a, b, 400)
+
N_vals = [5, 10, 20]
  
# Lista de colores para cada aproximación
+
# Puntos para graficar
colores = [ "#0000FF","#0066CC", "#33CCFF",]
+
x_vals = np.linspace(a, b, 500)
 +
f_vals = f(x_vals)
  
# Graficar aproximaciones con 5, 10 y 20 términos
+
# Graficar
plt.figure(figsize=(10, 6), dpi=200)
+
plt.figure(figsize=(10, 6))
plt.plot(X, f(X), label="Función original f(x)", linewidth=2, color="black") # Función original en negro
+
plt.plot(x_vals, f_vals, 'k', label="Función original f(x)", linewidth=2)
  
for i, N in enumerate([5, 10, 20]):
+
colores = ['b', 'dodgerblue', "#66CCCC"]
     plt.plot(X, [aproximacion_fourier(x, N) for x in X], label=f"Aprox. con {N} términos", color=colores[i])
+
for i, N in enumerate(N_vals):
 +
     f_aprox_vals = np.array([fourier_aprox(x, N) for x in x_vals])
 +
    plt.plot(x_vals, f_aprox_vals, color=colores[i], label=f"Aprox. con {N} términos")
  
 
plt.legend()
 
plt.legend()
 
plt.grid()
 
plt.grid()
plt.title("Aproximación de f(x) mediante series de Fourier en [-2,3]")
+
plt.title("Aproximación de Fourier de f(x) = x e^(-x)")
 
plt.xlabel("x")
 
plt.xlabel("x")
 
plt.ylabel("f(x)")
 
plt.ylabel("f(x)")

Revisión del 11:56 15 feb 2025

Trabajo realizado por estudiantes
Título Series de Fourier (Grupo ILIA)
Asignatura EDP
Curso 2024-25
Autores Ignacio Campos Paños, Ignacio Martínez Cerezo, Luis Ramos Ortiz, Alicia Ruiz Dominguez
Este artículo ha sido escrito por estudiantes como parte de su evaluación en la asignatura

1 Introducción

En una amplia gama de problemas de ingeniería y matemáticas aparecen funciones periódicas que se necesitan aproximar mediante sumas de funciones trigonométricas, lo que conduce a las series de Fourier.

Jean-Baptiste Joseph Fourier

Estas series constituyen una herramienta fundamental en la resolución de ecuaciones en derivadas parciales y otros muchos ámbitos de la ciencia. La idea principal es que una función [math]f(x)[/math], definida en un espacio de Hilbert [math]L^2(-\pi,\pi)[/math], puede expresarse como una combinación infinita de funciones trigonométricas de la forma:

[math] f(x) \approx \frac{d_0}{2\pi} + \sum_{n=1}^{\infty} d_n \frac{1}{\sqrt{\pi}} \cos(nx) + \sum_{n=1}^{\infty}c_n \frac{1}{\sqrt{\pi}} \sin(nx) [/math]


Los coeficientes [math]d_0[/math], [math]d_n[/math] y [math]c_n[/math] son los coeficientes de Fourier y se definen de la siguiente manera:

[math] \quad d_0 = \int_{-\pi}^{\pi} f(x) \frac{1}{\sqrt{\pi}} dx [/math]

[math] \quad d_n = \int_{-\pi}^{\pi} f(x) \frac{1}{\sqrt{\pi}}cos(nx) dx [/math]

[math] \quad c_n = \int_{-\pi}^{\pi} f(x) \frac{1}{\sqrt{\pi}}sen(nx) dx [/math]


Este método permite descomponer funciones periódicas en sus componentes fundamentales, lo que es de gran utilidad en física, ingeniería y matemáticas aplicadas. A continuación, se presentan las primeras funciones base utilizadas en la expansión en series de Fourier.

2 Base trigonométrica

Para comprender mejor la construcción de las series de Fourier y poder visualizar las funciones base mencionadas, representamos gráficamente los primeros términos de la base trigonométrica [math] \mathcal{B} := \left\{ \frac{1}{2}, \cos(n\pi x), \sin(n\pi x) \right\}_{n \in \mathbb{N}} [/math] en el intervalo [math] [ -1, 1 ] [/math] mediante un código en Python. Esto nos permitirá observar cómo estas funciones elementales forman una base ortonormal en el espacio [math] L^2( [-1,1]) [/math] y cómo, mediante combinaciones lineales de estas, podemos aproximar funciones arbitrarias.


Primeros términos de la Base Trigonométrica
import numpy as np
import matplotlib.pyplot as plt


def base_fourier_cos(n: int) -> list[callable]:
    """Genera los n primeros términos de cosenos de la base trigonométrica de fourier

    Args:
        n (int): Número de términos

    Returns:
        list[callable]: lista con funciones lambda, ordenada según su posición en la base.
    """
    basis_functions = []
    for k in range(1, n + 1):
        basis_functions.append(lambda x, k=k: np.cos(np.pi * k * x))
    return basis_functions


def base_fourier_sen(n: int) -> list[callable]:
    """Genera los n primeros términos de senos de la base trigonométrica de fourier

    Args:
        n (int): Número de términos

    Returns:
        list[callable]: lista con funciones lambda, ordenada según su posición en la base.
    """
    basis_functions = []
    for k in range(1, n + 1):
        basis_functions.append(lambda x, k=k: np.sin(np.pi * k * x))
    return basis_functions


# Parámetros
X = np.linspace(-1, 1, 1000)
# número de elementos de la base (1, cos(n pi x), sen(n pi x))
n = 10


colors = [ "#0000FF", "#0033CC", "#0066CC", "#0099FF", "#33CCFF",
    "#66CCCC", "#CC9966", "#FF6633", "#FF3300", "#FF0000",]


# Obtener funciones base
base = [lambda x: 1] + base_fourier_cos(n) + base_fourier_sen(n)


# Graficar
plt.subplots(3, 1, figsize=(15, 15), dpi=300)

# Término constante
plt.subplot(3, 1, 1)
plt.grid()
plt.title("Término constante")
plt.plot([-1, 1], [1 / 2, 1 / 2], color=colors[-1], label="Término constante")

# Términos en coseno
plt.subplot(3, 1, 2)
plt.grid()
plt.title("Términos en coseno")
for i in range(1, n + 1):
    plt.plot(X, base[i](X), color=colors[i - 1], label=f"cos({str(i)*(i>1)}πx)")
plt.legend(loc="right")

# Términos en seno
plt.subplot(3, 1, 3)
plt.grid()
plt.title("Términos en seno")
for i in range(n + 1, len(base)):
    plt.plot(X, base[i](X), color=colors[i - n - 1], label=f"sen({str(i-n) * ((i-n) > 1)}πx)")
plt.legend()


Fourier según aumenta n

Al graficar estos términos, podemos apreciar cómo la combinación de estos elementos nos permite aproximar funciones periódicas arbitrarias, tal y como buscábamos. La relevancia de esta base radica en la aproximación de funciones mediante series trigonométricas. En particular, la expansión de Fourier de una función \( f(x) \) en esta base se expresa como:

[math] f(x) \approx \sum_{n=1}^{\infty} c_n e_n \quad \text{con} \quad c_n = \langle f, e_n \rangle [/math]


Donde \( e_n \) es cada uno de los términos de la base [math] \left\{ \frac{1}{2}, \cos(n\pi x), \sin(n\pi x) \right\}_{n \in \mathbb{N}} [/math], y [math] c_n [/math] son los coeficientes que se calculan mediante el producto interno de [math] f(x) [/math] con los elementos de la base.

Como se puede observar, a medida que el parámetro [math] n [/math] aumenta, los términos oscilan con un periodo cada vez menor, concretamente [math] T = \frac{2}{n} [/math], lo que refleja una mayor "frecuencia" en las oscilaciones. Esta característica es esencial en la aproximación de funciones suaves por medio de las series de Fourier, donde las funciones periódicas se aproximan cada vez con mayor precisión mediante una combinación lineal de estos términos básicos.


3 Cambio de intervalo

Una vez se ha trabajado en la base trigonométrica [math] [-1,1] [/math], es importante señalar que en la práctica es común encontrar funciones definidas en otros dominios. En este apartado, se construirá la base trigonométrica en un nuevo intervalo, [math] [-2,3] [/math], y se usará esta base para aproximar la función

[math] f(x)=xe^{-x} [/math]

mediante series de Fourier, considerando los primeros [math] 5, 10 [/math] y [math] 20 [/math] términos.


3.1 Construcción de la base trigonométrica en [math] [-2,3] [/math]

En un intervalo general [math] [a,b] [/math], la base trigonométrica asociada está dada por:

[math] \left\{ \frac{1}{\sqrt{b-a}}, \cos\left(\frac{n\pi (x-a)}{b-a} \right), \sin\left(\frac{n\pi (x-a)}{b-a} \right) \right\}_{n \in \mathbb{N}} [/math]

donde se ha normalizado el término constante para que la base sea ortonormal en [math] L^2 ([a,b]) [/math].

En nuestro caso, con [math] a=-2 [/math] y [math] b=3 [/math], la base trigonométrica resulta:

[math] \left\{ \frac{1}{\sqrt{5}}, \cos\left(\frac{n\pi (x+2)}{5} \right), \sin\left(\frac{n\pi (x+2)}{5} \right) \right\}_{n \in \mathbb{N}} [/math]

3.2 Cálculo de los coeficientes de Fourier

Para expandir la función [math] f(x)=xe^{-x} [/math] en esta nueva base, es necesario calcular los coeficientes de Fourier:

[math] c_n = \int_{-2}^{3} f(x)e_n(x) dx [/math]

donde [math] e_n [/math] son los términos de la base calculada anteriormente.

El cálculo de estos coeficientes implica integrar productos de [math] f(x) [/math] con funciones trigonométricas, lo que puede llegar a ser muy laborioso para [math] 5, 10 [/math] y [math] 20 [/math] términos, y es por esto que estos cálculos se hacen mediante herramientas computacionales como Python. A continuación, se incluye el código que nos proporciona la aproximación que buscábamos.

Aproximación de f(x) mediante series de Fourier
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import quad

# Intervalo
a, b = -2, 3
L = (b - a) / 2  # Semi-longitud del intervalo

# Función a aproximar
def f(x):
    return x * np.exp(-x)

# Coeficiente a_0
def a_0():
    return (1 / L) * quad(lambda x: f(x), a, b)[0]

# Coeficientes a_n y b_n
def a_n(n):
    return (1 / L) * quad(lambda x: f(x) * np.cos(n * np.pi * (x - a) / L), a, b)[0]

def b_n(n):
    return (1 / L) * quad(lambda x: f(x) * np.sin(n * np.pi * (x - a) / L), a, b)[0]

# Aproximación de Fourier con N términos
def fourier_aprox(x, N):
    suma = a_0() / 2
    for n in range(1, N + 1):
        suma += a_n(n) * np.cos(n * np.pi * (x - a) / L) + b_n(n) * np.sin(n * np.pi * (x - a) / L)
    return suma

# Valores de N a considerar
N_vals = [5, 10, 20]

# Puntos para graficar
x_vals = np.linspace(a, b, 500)
f_vals = f(x_vals)

# Graficar
plt.figure(figsize=(10, 6))
plt.plot(x_vals, f_vals, 'k', label="Función original f(x)", linewidth=2)

colores = ['b', 'dodgerblue', "#66CCCC"]
for i, N in enumerate(N_vals):
    f_aprox_vals = np.array([fourier_aprox(x, N) for x in x_vals])
    plt.plot(x_vals, f_aprox_vals, color=colores[i], label=f"Aprox. con {N} términos")

plt.legend()
plt.grid()
plt.title("Aproximación de Fourier de f(x) = x e^(-x)")
plt.xlabel("x")
plt.ylabel("f(x)")
plt.show()

En las aproximaciones con un mayor número de n aparecen oscilaciones más pronunciadas, y la aproximación es peor en ciertos puntos. Esto es el llamado fenómeno de Gibbs.