Diferencia entre revisiones de «Series de Fourier (Grupo PPAD)»
| (No se muestran 18 ediciones intermedias de 3 usuarios) | |||
| Línea 4: | Línea 4: | ||
Se define el espacio de Hilbert <math>L^2(a,b)</math> como: | Se define el espacio de Hilbert <math>L^2(a,b)</math> como: | ||
<center><math> L^2(a,b) = \left\{ f(x)| \int_{a}^{b} |f(x)|^{2} dx \lt \infty \right\} </math>,</center> | <center><math> L^2(a,b) = \left\{ f(x)| \int_{a}^{b} |f(x)|^{2} dx \lt \infty \right\} </math>,</center> | ||
| − | donde <math> a,b \in \mathbb{R} </math> y <math> a \lt b </math>. <math>L^2(a,b)</math> es un espacio | + | 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: |
<center><math> \left\langle f,g \right\rangle_{L^{2}}=\int_{a}^{b} f(x)g(x) dx, \forall f,g \in L^{2} </math>,</center> | <center><math> \left\langle f,g \right\rangle_{L^{2}}=\int_{a}^{b} f(x)g(x) dx, \forall f,g \in L^{2} </math>,</center> | ||
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. | 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. | ||
| Línea 12: | Línea 12: | ||
<center><math> \beta = \left\{ \frac{1}{\sqrt{2\pi}}, \frac{1}{\sqrt{\pi}}cos(n x), \frac{1}{\sqrt{\pi}}sen(n x) \right\}_{n \in \mathbb{N}} </math>,</center> | <center><math> \beta = \left\{ \frac{1}{\sqrt{2\pi}}, \frac{1}{\sqrt{\pi}}cos(n x), \frac{1}{\sqrt{\pi}}sen(n x) \right\}_{n \in \mathbb{N}} </math>,</center> | ||
que se conoce como referencia de Fourier trigonométrica. | que se conoce como referencia de Fourier trigonométrica. | ||
| + | <br/> | ||
| + | <br/> | ||
| + | <br/> | ||
| + | [[Archivo:PPAD1.jpeg|800px|thumb|Término constante de la base]] | ||
| + | [[Archivo:PPAD2.jpeg|800px|thumb|Primeros 10 elementos del coseno de la base]] | ||
| + | [[Archivo:PPAD3.jpeg|800px|thumb|Primeros 10 elementos del seno de la base]] | ||
| + | <syntaxhighlight lang="python"> | ||
| + | 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() | ||
| + | |||
| + | </syntaxhighlight> | ||
| + | |||
| + | <syntaxhighlight lang="python"> | ||
| + | |||
| + | 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() | ||
| + | |||
| + | </syntaxhighlight> | ||
=. Aproximación de una función por la base trigonométrica= | =. Aproximación de una función por la base trigonométrica= | ||
| Línea 29: | Línea 98: | ||
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 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) \): | De esta forma, obtenemos la base de Fourier de \( L^2(a,b) \): | ||
| Línea 60: | Línea 112: | ||
para los términos trigonométricos. | para los términos trigonométricos. | ||
| + | |||
| + | Una función \( f(x) \in L^2(a,b) \) puede escribirse entonces: | ||
| + | |||
| + | <center><math> | ||
| + | f(x) = \frac{d_0}{\sqrt{b-a}} + \sum_{n=0}^{\infty} \frac{\sqrt{2}}{\sqrt{b-a}} d_n \cos(n h(x)) + \sum_{n=0}^{\infty} \frac{\sqrt{2}}{\sqrt{b-a}} c_n \sin(n h(x)) | ||
| + | </math></center> | ||
En <math> L^2(-2,3) </math>, nos queda la base: | En <math> L^2(-2,3) </math>, nos queda la base: | ||
| Línea 100: | Línea 158: | ||
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: | 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: | ||
| + | <br/> | ||
| + | <br/> | ||
| + | <br/> | ||
| + | [[Archivo:Fourier.gif|800px|thumb|Aproximación de Fourier de la función extendida <math> xe^{-x} </math>]] | ||
| + | [[Archivo:Error_fourier.gif|800px|thumb|Error absoluto entre la función <math> xe^{-x} </math> y su aproximación de Fourier]] | ||
| − | |||
| − | |||
| + | [[Archivo:Error_supremo.png|800px|thumb|Error en norma supremo de la aproximación para distintos valores de n]] | ||
| + | [[Archivo:Error_L2.png|800px|thumb|Error en norma L2 de la aproximación para distintos valores de n]] | ||
| + | |||
| + | <syntaxhighlight lang="python"> | ||
| − | |||
from tqdm import tqdm | from tqdm import tqdm | ||
import sympy as sp | import sympy as sp | ||
| Línea 112: | Línea 176: | ||
import numpy as np | import numpy as np | ||
import matplotlib.pyplot as plt | import matplotlib.pyplot as plt | ||
| − | |||
| − | |||
| − | |||
| − | + | n=10 | |
| − | + | ||
| + | def calcular_aproximacion_fourier(n): | ||
| + | e = 0 | ||
| + | l = 0 | ||
x = sp.symbols('x') | 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)) | + | d0 = -(4 + sp.exp(5)) / (math.sqrt(5) * sp.exp(3)) |
| − | + | f = d0 / math.sqrt(5) + e + l | |
| − | f=d0/math.sqrt(5)+e+l | + | |
| − | + | return sp.lambdify(x, f, "numpy") | |
| − | + | ||
# Definir la función f(x) = x * exp(-x) | # Definir la función f(x) = x * exp(-x) | ||
| Línea 147: | Línea 211: | ||
y_vals = f(x_vals) | y_vals = f(x_vals) | ||
| + | f_numeric=calcular_aproximacion_fourier(n) | ||
# Aproximación de Fourier (f_numeric debe estar definida previamente) | # Aproximación de Fourier (f_numeric debe estar definida previamente) | ||
y_fourier = f_numeric(x_vals) | y_fourier = f_numeric(x_vals) | ||
| Línea 176: | Línea 241: | ||
plt.show | 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() | ||
| + | </syntaxhighlight> | ||
Revisión actual del 22:12 23 feb 2025
| 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(x) \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).






