<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es">
		<id>https://mat.caminos.upm.es/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=DiegoGR</id>
		<title>MateWiki - Contribuciones del usuario [es]</title>
		<link rel="self" type="application/atom+xml" href="https://mat.caminos.upm.es/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=DiegoGR"/>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/wiki/Especial:Contribuciones/DiegoGR"/>
		<updated>2026-04-23T14:55:12Z</updated>
		<subtitle>Contribuciones del usuario</subtitle>
		<generator>MediaWiki 1.26.2</generator>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104643</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104643"/>
				<updated>2026-04-15T06:44:53Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:EcCalor PDM-1(1).png|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:EcCalor_PDM-1(1).png&amp;diff=104642</id>
		<title>Archivo:EcCalor PDM-1(1).png</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:EcCalor_PDM-1(1).png&amp;diff=104642"/>
				<updated>2026-04-15T06:44:15Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104634</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104634"/>
				<updated>2026-04-12T22:00:36Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:PosterEcCalorFinalPDM.png|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterEcCalorFinalPDM.png&amp;diff=104633</id>
		<title>Archivo:PosterEcCalorFinalPDM.png</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterEcCalorFinalPDM.png&amp;diff=104633"/>
				<updated>2026-04-12T21:59:49Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterEcCalorFinal.png&amp;diff=104630</id>
		<title>Archivo:PosterEcCalorFinal.png</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterEcCalorFinal.png&amp;diff=104630"/>
				<updated>2026-04-12T21:56:17Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104625</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104625"/>
				<updated>2026-04-12T21:50:23Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Poster */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:PosterEcCalor-1.png|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterEcCalor-1.png&amp;diff=104620</id>
		<title>Archivo:PosterEcCalor-1.png</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterEcCalor-1.png&amp;diff=104620"/>
				<updated>2026-04-12T21:48:04Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104612</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104612"/>
				<updated>2026-04-12T21:43:28Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:PosterEcCalor.pdf|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterEcCalor.pdf&amp;diff=104608</id>
		<title>Archivo:PosterEcCalor.pdf</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterEcCalor.pdf&amp;diff=104608"/>
				<updated>2026-04-12T21:42:21Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104607</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104607"/>
				<updated>2026-04-12T21:40:41Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Principio del máximo y aproximación de la solución por convolución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104606</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104606"/>
				<updated>2026-04-12T21:40:04Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&amp;lt;\pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&amp;lt;\pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;\pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104605</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104605"/>
				<updated>2026-04-12T21:39:39Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;\pre&amp;gt;&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&amp;lt;\pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&amp;lt;\pre&amp;gt;&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;\pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104604</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104604"/>
				<updated>2026-04-12T21:37:44Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104603</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104603"/>
				<updated>2026-04-12T21:37:28Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104601</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104601"/>
				<updated>2026-04-12T21:36:44Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104600</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104600"/>
				<updated>2026-04-12T21:36:08Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104599</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104599"/>
				<updated>2026-04-12T21:35:01Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
====Principio del máximo y aproximación de la solución por convolución====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
====Decaimiento y principio del máximo Dirichlet====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
====Decaimiento y principio del máximo Neumann====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104597</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104597"/>
				<updated>2026-04-12T21:34:11Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
====Decaimiento puntual y en L^2 en caso no acotado=====&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
============================Principio del máximo y aproximación de la solución por convolución========================================&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
============================Decaimiento y principio del máximo Dirichlet========================================&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
============================Decaimiento y principio del máximo Neumann========================================&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104595</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104595"/>
				<updated>2026-04-12T21:32:56Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
============================Decaimiento puntual y en L^2 en caso no acotado========================================&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial y temporal&lt;br /&gt;
x = linspace(-8,8,600);&lt;br /&gt;
t = linspace(0.001,10,120);&lt;br /&gt;
y = linspace(-1,1,400);   % variable de integracion del dato inicial&lt;br /&gt;
&lt;br /&gt;
%% Solucion fundamental&lt;br /&gt;
G = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% Calculo de la solucion U(t,x)&lt;br /&gt;
U = zeros(length(t), length(x));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    tn = t(n);&lt;br /&gt;
    for i = 1:length(x)&lt;br /&gt;
        integrando = G(x(i)-y, tn);   % porque u0(y)=1 en [-1,1]&lt;br /&gt;
        U(n,i) = trapz(y, integrando);&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 1. Decaimiento puntual&lt;br /&gt;
%% =========================&lt;br /&gt;
% Elegimos algunos puntos fijos&lt;br /&gt;
x_pts = [-0.5, 0, 0.5 1, 2, 4];&lt;br /&gt;
idx = zeros(size(x_pts));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    [~, idx(k)] = min(abs(x - x_pts(k)));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(x_pts)&lt;br /&gt;
    plot(t, U(:,idx(k)), 'LineWidth', 2);&lt;br /&gt;
end&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x_0,t)');&lt;br /&gt;
title('Decaimiento puntual de la solucion');&lt;br /&gt;
legend('x=-0.5','x=0','x=0.5','x=1','x=2','x=4','Location','best');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 2. Decaimiento en norma L2&lt;br /&gt;
%% =========================&lt;br /&gt;
L2 = zeros(size(t));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(t)&lt;br /&gt;
    L2(n) = sqrt(trapz(x, U(n,:).^2));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
plot(t, L2, 'LineWidth', 2);&lt;br /&gt;
grid on;&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('||u(\cdot,t)||_{L^2}');&lt;br /&gt;
title('Decaimiento en norma L^2');&lt;br /&gt;
&lt;br /&gt;
%% =========================&lt;br /&gt;
%% 3. Superficie 3D opcional&lt;br /&gt;
%% =========================&lt;br /&gt;
[X,T] = meshgrid(x,t);&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
surf(X,T,U);&lt;br /&gt;
shading interp;&lt;br /&gt;
colorbar;&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('t');&lt;br /&gt;
zlabel('u(x,t)');&lt;br /&gt;
title('Solucion u(x,t)');&lt;br /&gt;
view(135,30);&lt;br /&gt;
&lt;br /&gt;
============================Principio del máximo y aproximación de la solución por convolución========================================&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% PRINCIPIO DEL MAXIMO - ECUACION DEL CALOR EN R&lt;br /&gt;
% Casos:&lt;br /&gt;
% 1) u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
% 2) u0(x) = exp(-x^2)&lt;br /&gt;
%&lt;br /&gt;
% Se usa la formula de convolucion:&lt;br /&gt;
% u(x,t) = \int Phi(x-y,t) u0(y) dy&lt;br /&gt;
% donde Phi(x,t) = 1/sqrt(4*pi*t) * exp(-x^2/(4*t))&lt;br /&gt;
&lt;br /&gt;
clear; close all; clc;&lt;br /&gt;
&lt;br /&gt;
%% Mallado espacial para representar la solucion&lt;br /&gt;
x = linspace(-6,6,1600);&lt;br /&gt;
&lt;br /&gt;
%% Instantes de tiempo&lt;br /&gt;
tvals = [0.005 0.02 0.1 0.5];&lt;br /&gt;
&lt;br /&gt;
%% Nucleo de calor&lt;br /&gt;
Phi = @(z,t) (1./sqrt(4*pi*t)) .* exp(-(z.^2)./(4*t));&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 1: u0(x) = 1_{[-1,1]}(x)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_1 = @(x) double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Para la integral solo hace falta integrar en [-1,1]&lt;br /&gt;
y1 = linspace(-1,1,2500);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 1: u0 = 1_{[-1,1]}');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_1(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('============================\n');&lt;br /&gt;
fprintf('CASO 1: u0(x) = 1_{[-1,1]}(x)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_1(x)), max(u0_1(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    % Matriz Z(i,j)=x_i-y_j&lt;br /&gt;
    Z = x(:) - y1(:).';&lt;br /&gt;
    integrando = Phi(Z,t);           &lt;br /&gt;
    U = trapz(y1, integrando, 2).';  &lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el primer problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% CASO 2: u0(x) = exp(-x^2)&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
u0_2 = @(x) exp(-x.^2);&lt;br /&gt;
&lt;br /&gt;
% Aproximamos la integral en un intervalo grande&lt;br /&gt;
y2 = linspace(-8,8,4000);&lt;br /&gt;
&lt;br /&gt;
figure('Name','Caso 2: u0 = exp(-x^2)');&lt;br /&gt;
hold on; grid on;&lt;br /&gt;
&lt;br /&gt;
% Dato inicial&lt;br /&gt;
plot(x,u0_2(x),'k--','LineWidth',1.8,'DisplayName','$u_0(x)$');&lt;br /&gt;
&lt;br /&gt;
fprintf('\n============================\n');&lt;br /&gt;
fprintf('CASO 2: u0(x) = exp(-x^2)\n');&lt;br /&gt;
fprintf('Dato inicial: min = %.6f, max = %.6f\n', min(u0_2(x)), max(u0_2(x)));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(tvals)&lt;br /&gt;
    t = tvals(k);&lt;br /&gt;
&lt;br /&gt;
    Z = x(:) - y2(:).';&lt;br /&gt;
    integrando = Phi(Z,t) .* exp(-(y2.^2));&lt;br /&gt;
    U = trapz(y2, integrando, 2).';&lt;br /&gt;
&lt;br /&gt;
    plot(x,U,'LineWidth',1.8,'DisplayName',['$t=', num2str(t), '$']);&lt;br /&gt;
&lt;br /&gt;
    fprintf('t = %.4f --&amp;gt; min = %.6f, max = %.6f\n', t, min(U), max(U));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
title('Principio del máximo en el segundo problema','Interpreter','latex');&lt;br /&gt;
xlabel('$x$','Interpreter','latex');&lt;br /&gt;
&lt;br /&gt;
ylabel('$u(x,t)$','Interpreter','latex');&lt;br /&gt;
legend('Location','best','Interpreter','latex');&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%% EVOLUCION DE MAXIMOS Y MINIMOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
tgrid = linspace(0.005,0.5,60);&lt;br /&gt;
&lt;br /&gt;
max1 = zeros(size(tgrid));&lt;br /&gt;
min1 = zeros(size(tgrid));&lt;br /&gt;
max2 = zeros(size(tgrid));&lt;br /&gt;
min2 = zeros(size(tgrid));&lt;br /&gt;
&lt;br /&gt;
for n = 1:length(tgrid)&lt;br /&gt;
    t = tgrid(n);&lt;br /&gt;
&lt;br /&gt;
    % Caso 1&lt;br /&gt;
    Z1 = x(:) - y1(:).';&lt;br /&gt;
    U1 = trapz(y1, Phi(Z1,t), 2).';&lt;br /&gt;
    max1(n) = max(U1);&lt;br /&gt;
    min1(n) = min(U1);&lt;br /&gt;
&lt;br /&gt;
    % Caso 2&lt;br /&gt;
    Z2 = x(:) - y2(:).';&lt;br /&gt;
    U2 = trapz(y2, Phi(Z2,t).*exp(-(y2.^2)), 2).';&lt;br /&gt;
    max2(n) = max(U2);&lt;br /&gt;
    min2(n) = min(U2);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure('Name','Evolucion de maximos y minimos');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,1)&lt;br /&gt;
plot(tgrid,max1,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min1,'LineWidth',1.8);&lt;br /&gt;
title('Caso 1: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
subplot(1,2,2)&lt;br /&gt;
plot(tgrid,max2,'LineWidth',1.8); hold on; grid on;&lt;br /&gt;
plot(tgrid,min2,'LineWidth',1.8);&lt;br /&gt;
title('Caso 2: máximos y mínimos','Interpreter','latex');&lt;br /&gt;
xlabel('$t$','Interpreter','latex');&lt;br /&gt;
ylabel('valor','Interpreter','latex');&lt;br /&gt;
legend({'$\max u(\cdot,t)$','$\min u(\cdot,t)$'},'Interpreter','latex','Location','best');&lt;br /&gt;
&lt;br /&gt;
============================Decaimiento y principio del máximo Dirichlet========================================&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  ECUACION DEL CALOR 1D CON DIRICHLET&lt;br /&gt;
%&lt;br /&gt;
%    u_t - u_xx = 0,     x in (-6,6), t&amp;gt;0&lt;br /&gt;
%    u(-6,t) = 0,        u(6,t) = 0&lt;br /&gt;
%    u(x,0) = 1_{[-1,1]}(x)&lt;br /&gt;
%&lt;br /&gt;
%  Este script:&lt;br /&gt;
%   1) Resuelve el problema&lt;br /&gt;
%   2) Grafica u(x_i,t) en puntos fijos (decaimiento temporal)&lt;br /&gt;
%   3) Muestra la superficie 3D u(x,t) (principio del maximo)&lt;br /&gt;
%   4) Grafica perfiles espaciales x -&amp;gt; u(x,t) para tiempos fijos&lt;br /&gt;
%% ============================================================&lt;br /&gt;
&lt;br /&gt;
%% Parametros del dominio&lt;br /&gt;
a = -6;&lt;br /&gt;
b = 6;&lt;br /&gt;
Nx = 401;                      % nodos espaciales totales&lt;br /&gt;
x = linspace(a,b,Nx)';         % columna&lt;br /&gt;
dx = x(2)-x(1);&lt;br /&gt;
&lt;br /&gt;
%% Parametros temporales&lt;br /&gt;
Tmax = 8;                      % tiempo final&lt;br /&gt;
Nt = 300;                      % numero de tiempos para guardar&lt;br /&gt;
tspan = linspace(0,Tmax,Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condicion inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
% Compatibilidad con Dirichlet en bordes&lt;br /&gt;
u0(1) = 0;&lt;br /&gt;
u0(end) = 0;&lt;br /&gt;
&lt;br /&gt;
u0_max = max(u0);&lt;br /&gt;
u0_min = min(u0);&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo inicial = %.6f\n', u0_max);&lt;br /&gt;
fprintf('Minimo inicial = %.6f\n', u0_min);&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Discretizacion espacial&lt;br /&gt;
%  Solo resolvemos en nodos interiores&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Nint = Nx - 2;                 % numero de nodos interiores&lt;br /&gt;
xint = x(2:end-1);&lt;br /&gt;
u0int = u0(2:end-1);&lt;br /&gt;
&lt;br /&gt;
e = ones(Nint,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nint, Nint) / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Sistema semidiscreto:&lt;br /&gt;
%      U_t = A U&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
&lt;br /&gt;
% Solver rigido adecuado para difusion&lt;br /&gt;
[t,Uint] = ode15s(f, tspan, u0int);&lt;br /&gt;
&lt;br /&gt;
%% Reconstruccion de la solucion completa incluyendo bordes&lt;br /&gt;
% Ufull(j,i) = u(x_i, t_j)&lt;br /&gt;
Ufull = zeros(length(t), Nx);&lt;br /&gt;
Ufull(:,2:end-1) = Uint;&lt;br /&gt;
Ufull(:,1) = 0;&lt;br /&gt;
Ufull(:,end) = 0;&lt;br /&gt;
&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
%  Comprobacion numerica del principio del maximo&lt;br /&gt;
%% ------------------------------------------------------------&lt;br /&gt;
Umax = max(Ufull(:));&lt;br /&gt;
Umin = min(Ufull(:));&lt;br /&gt;
&lt;br /&gt;
fprintf('Maximo global numerico de la solucion = %.6f\n', Umax);&lt;br /&gt;
fprintf('Minimo global numerico de la solucion = %.6f\n', Umin);&lt;br /&gt;
fprintf('Deberia cumplirse aproximadamente: 0 &amp;lt;= u(x,t) &amp;lt;= 1\n');&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  1) DECAIMIENTO TEMPORAL EN PUNTOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, Ufull(:,obs_idx(k)), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos (Dirichlet)');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% ============================================================&lt;br /&gt;
%  3) PERFILES ESPACIALES x -&amp;gt; u(x,t) PARA TIEMPOS FIJOS&lt;br /&gt;
%% ============================================================&lt;br /&gt;
times_to_plot = [0 0.19 0.99 3.99 8];&lt;br /&gt;
&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, Ufull(j,:), 'LineWidth', 1.6, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales para tiempos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
hold off;&lt;br /&gt;
&lt;br /&gt;
============================Decaimiento y principio del máximo Neumann========================================&lt;br /&gt;
clear; clc; close all;&lt;br /&gt;
&lt;br /&gt;
%% Dominio espacial&lt;br /&gt;
L = 6;&lt;br /&gt;
Nx = 401;&lt;br /&gt;
x = linspace(-L, L, Nx)';&lt;br /&gt;
dx = x(2) - x(1);&lt;br /&gt;
&lt;br /&gt;
%% Tiempo&lt;br /&gt;
Tmax = 20;&lt;br /&gt;
Nt = 300;&lt;br /&gt;
tspan = linspace(0, Tmax, Nt);&lt;br /&gt;
&lt;br /&gt;
%% Condición inicial: 1_{[-1,1]}(x)&lt;br /&gt;
u0 = double(abs(x) &amp;lt;= 1);&lt;br /&gt;
&lt;br /&gt;
%% Media integral de la condición inicial&lt;br /&gt;
media = trapz(x, u0) / (2*L);&lt;br /&gt;
fprintf('Media integral numerica = %.8f\n', media);&lt;br /&gt;
fprintf('Media exacta            = %.8f\n', 1/6);&lt;br /&gt;
&lt;br /&gt;
%% Matriz del Laplaciano con Neumann homogéneas&lt;br /&gt;
e = ones(Nx,1);&lt;br /&gt;
A = spdiags([e -2*e e], -1:1, Nx, Nx);&lt;br /&gt;
&lt;br /&gt;
% Ajuste en bordes para Neumann: u_x = 0&lt;br /&gt;
A(1,1)   = -2;&lt;br /&gt;
A(1,2)   =  2;&lt;br /&gt;
A(end,end-1) = 2;&lt;br /&gt;
A(end,end)   = -2;&lt;br /&gt;
&lt;br /&gt;
A = A / dx^2;&lt;br /&gt;
&lt;br /&gt;
%% Resolver sistema semidiscreto U_t = A*U&lt;br /&gt;
% ode15s va bien para difusión&lt;br /&gt;
f = @(t,u) A*u;&lt;br /&gt;
[t,U] = ode15s(f, tspan, u0);&lt;br /&gt;
&lt;br /&gt;
% U sale como matriz Nt x Nx&lt;br /&gt;
% para acceder a u(x_i,t_j): U(j,i)&lt;br /&gt;
&lt;br /&gt;
%% Puntos de observación: desde 0 y alejándose&lt;br /&gt;
obs_points = [0 0.5 1 2 3 4 5];&lt;br /&gt;
obs_idx = zeros(size(obs_points));&lt;br /&gt;
obs_real = zeros(size(obs_points));&lt;br /&gt;
&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    [~, obs_idx(k)] = min(abs(x - obs_points(k)));&lt;br /&gt;
    obs_real(k) = x(obs_idx(k));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
%% Figura 1: evolución temporal en puntos fijos&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for k = 1:length(obs_points)&lt;br /&gt;
    plot(t, U(:, obs_idx(k)), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('x = %.2f', obs_real(k)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('t');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Decaimiento temporal en puntos fijos');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%% Figura 3: perfiles espaciales para tiempos concretos&lt;br /&gt;
times_to_plot = [0 0.2 1 5 20];&lt;br /&gt;
figure;&lt;br /&gt;
hold on;&lt;br /&gt;
for m = 1:length(times_to_plot)&lt;br /&gt;
    [~, j] = min(abs(t - times_to_plot(m)));&lt;br /&gt;
    plot(x, U(j,:), 'LineWidth', 1.5, ...&lt;br /&gt;
        'DisplayName', sprintf('t = %.2f', t(j)));&lt;br /&gt;
end&lt;br /&gt;
yline(media, '--k', 'LineWidth', 2, 'DisplayName', 'media = 1/6');&lt;br /&gt;
xlabel('x');&lt;br /&gt;
ylabel('u(x,t)');&lt;br /&gt;
title('Perfiles espaciales');&lt;br /&gt;
legend('Location','best');&lt;br /&gt;
grid on;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104588</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104588"/>
				<updated>2026-04-12T21:20:23Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104587</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104587"/>
				<updated>2026-04-12T21:20:03Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104586</id>
		<title>Ecuación del calor PDM</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_PDM&amp;diff=104586"/>
				<updated>2026-04-12T21:18:47Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: Página creada con «{{ TrabajoED | Ecuación del calor PDM| EDP|2025-26 | Diego García Raposo  Paula Dopico Muñoz  Manuel Herreros Zarco}}  ==Ecu...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor PDM| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Ecuación del calor==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier(PDM)&amp;diff=104378</id>
		<title>Series de Fourier(PDM)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier(PDM)&amp;diff=104378"/>
				<updated>2026-02-23T22:33:11Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Poster */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:PosterFInal VF(1).png|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterFInal_VF(1).png&amp;diff=104377</id>
		<title>Archivo:PosterFInal VF(1).png</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterFInal_VF(1).png&amp;diff=104377"/>
				<updated>2026-02-23T22:32:28Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterFInal_VF.png&amp;diff=104376</id>
		<title>Archivo:PosterFInal VF.png</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:PosterFInal_VF.png&amp;diff=104376"/>
				<updated>2026-02-23T22:26:30Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104324</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104324"/>
				<updated>2026-02-18T23:53:59Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: Página blanqueada&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier(PDM)&amp;diff=104323</id>
		<title>Series de Fourier(PDM)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier(PDM)&amp;diff=104323"/>
				<updated>2026-02-18T23:52:56Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier(PDM)&amp;diff=104321</id>
		<title>Series de Fourier(PDM)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier(PDM)&amp;diff=104321"/>
				<updated>2026-02-18T23:52:14Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Series de Fourier DPM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier(PDM)&amp;diff=104319</id>
		<title>Series de Fourier(PDM)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier(PDM)&amp;diff=104319"/>
				<updated>2026-02-18T23:52:00Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: Página creada con «{{ TrabajoED | Series de Fourier(DPM)| EDP|2025-26 | Diego García Raposo  Paula Dopico Muñoz  Manuel Herreros Zarco}}  ==Seri...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier DPM==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104317</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104317"/>
				<updated>2026-02-18T23:49:25Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier DPM==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104315</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104315"/>
				<updated>2026-02-18T23:48:54Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier DPM==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104314</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104314"/>
				<updated>2026-02-18T23:47:29Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Series de Fourier DPM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier DPM==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104312</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104312"/>
				<updated>2026-02-18T23:44:27Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Series de Fourier Grupo DPM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier DPM==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104311</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104311"/>
				<updated>2026-02-18T23:43:56Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Series de Fourier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier Grupo DPM==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104309</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104309"/>
				<updated>2026-02-18T23:40:07Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo&lt;br /&gt;
&lt;br /&gt;
Paula Dopico Muñoz&lt;br /&gt;
&lt;br /&gt;
Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104308</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104308"/>
				<updated>2026-02-18T23:39:49Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo-Paula Dopico Muñoz- Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104307</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104307"/>
				<updated>2026-02-18T23:39:23Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Series de Fourier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo-Paula Dopico Muñoz- Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP25/26]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104305</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104305"/>
				<updated>2026-02-18T23:36:33Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo-Paula Dopico Muñoz- Manuel Herreros Zarco}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104304</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104304"/>
				<updated>2026-02-18T23:36:14Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;nowiki&amp;gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo-Paula Dopico Muñoz- Manuel Herreros Zarco}}&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104302</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104302"/>
				<updated>2026-02-18T23:35:38Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo-Paula Dopico Muñoz- Manuel Herreros Zarco}}&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104298</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104298"/>
				<updated>2026-02-18T23:30:52Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Códigos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo - Paula Dopico Muñoz - Manuel Herreros Zarco.}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#nuevo código&lt;br /&gt;
import math&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- función de ejemplo ----------&lt;br /&gt;
def f(x):&lt;br /&gt;
    return x   # cambia aquí si quieres&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- coeficientes numéricos ----------&lt;br /&gt;
def fourier_coeffs_numeric(L, N, M=20000):&lt;br /&gt;
    xs = np.linspace(0.0, L, M)&lt;br /&gt;
    fx = f(xs)&lt;br /&gt;
&lt;br /&gt;
    a0 = (2.0 / L) * np.trapz(fx, xs)&lt;br /&gt;
&lt;br /&gt;
    a = np.zeros(N + 1)&lt;br /&gt;
    b = np.zeros(N + 1)&lt;br /&gt;
&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        c = np.cos(2.0 * math.pi * n * xs / L)&lt;br /&gt;
        s = np.sin(2.0 * math.pi * n * xs / L)&lt;br /&gt;
&lt;br /&gt;
        a[n] = (2.0 / L) * np.trapz(fx * c, xs)&lt;br /&gt;
        b[n] = (2.0 / L) * np.trapz(fx * s, xs)&lt;br /&gt;
&lt;br /&gt;
    return a0, a, b&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def S_N(x, L, N, a0, a, b):&lt;br /&gt;
    val = a0 / 2.0&lt;br /&gt;
    for n in range(1, N + 1):&lt;br /&gt;
        val += (&lt;br /&gt;
            a[n] * np.cos(2.0 * math.pi * n * x / L)&lt;br /&gt;
            + b[n] * np.sin(2.0 * math.pi * n * x / L)&lt;br /&gt;
        )&lt;br /&gt;
    return val&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --------- visualizar error en muchos puntos ----------&lt;br /&gt;
def visualize_error(Ls, N, num_points=500):&lt;br /&gt;
&lt;br /&gt;
    xs = np.linspace(0.001, min(Ls), num_points)  # intervalo común&lt;br /&gt;
&lt;br /&gt;
    plt.figure()&lt;br /&gt;
&lt;br /&gt;
    for L in Ls:&lt;br /&gt;
&lt;br /&gt;
        a0, a, b = fourier_coeffs_numeric(L, N)&lt;br /&gt;
&lt;br /&gt;
        approx = S_N(xs, L, N, a0, a, b)&lt;br /&gt;
        exact = f(xs)&lt;br /&gt;
&lt;br /&gt;
        error = np.abs(approx - exact)&lt;br /&gt;
&lt;br /&gt;
        plt.plot(xs, error, label=f&amp;quot;L={L}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    plt.yscale(&amp;quot;log&amp;quot;)&lt;br /&gt;
    plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
    plt.ylabel(&amp;quot;|S_N(x) - f(x)|&amp;quot;)&lt;br /&gt;
    plt.title(f&amp;quot;Error puntual para N={N}&amp;quot;)&lt;br /&gt;
    plt.legend()&lt;br /&gt;
    plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
    plt.show()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    Ls = [1.0, 4.0]&lt;br /&gt;
    N = 20&lt;br /&gt;
&lt;br /&gt;
    visualize_error(Ls, N, num_points=800)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) INTERVALO Y FUNCIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0 ### Inicio y final del intervalo&lt;br /&gt;
L = b - a ### Longitud intervalo&lt;br /&gt;
&lt;br /&gt;
def f(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0) ### Funcion indicatriz &lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MUESTREO&lt;br /&gt;
# =====================================================&lt;br /&gt;
M = 8192 ### Numero de puntos en x&lt;br /&gt;
x = np.linspace(a, b, M, endpoint=False) ### Genera un vector de M puntos entre a y b, pero no incluye el punto b&lt;br /&gt;
fx = f(x) ### Aplica la función a cada elementos del vector del linspace x tanto es un vector de lomgitud M&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) COEFICIENTES REALES DIRECTOS (SIN FFT)&lt;br /&gt;
# =====================================================&lt;br /&gt;
def coeffs_real_direct(fx, N, a=0.0, L=1.0):&lt;br /&gt;
    M = fx.size&lt;br /&gt;
    j = np.arange(M)&lt;br /&gt;
    xj = a + L*j/M  # mismos puntos que linspace(endpoint=False)&lt;br /&gt;
&lt;br /&gt;
    a0 = fx.mean()  # (1/M) sum f_j&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### np array, es decir una lista de las frecuencias ordenadas desde 0 hasta N, siendo N la mayor de la suma parcial deseada&lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (xj[None, :] - a) / L ### Crea una matriz donde el elemento Aij es 2*pi*k_i*x_j&lt;br /&gt;
&lt;br /&gt;
    ak = (2/M) * (fx[None, :] * np.cos(theta)).sum(axis=1) ### Calcula un vector donde cada elemento es el coeficiente asociado a la frecuencua ki&lt;br /&gt;
    bk = (2/M) * (fx[None, :] * np.sin(theta)).sum(axis=1) ### Lo mismo pero el seno&lt;br /&gt;
&lt;br /&gt;
    return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) RECONSTRUCCIÓN S_N EN BASE REAL&lt;br /&gt;
# =====================================================&lt;br /&gt;
def partial_sum_real_direct(N, x, fx, a=0.0, L=1.0):&lt;br /&gt;
    a0, ak, bk = coeffs_real_direct(fx, N, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    k = np.arange(1, N+1) ### Vector de frecuencias &lt;br /&gt;
    theta = 2*np.pi * k[:, None] * (x[None, :] - a) / L ### Genera una matriz elemento Aij es igual que antes pero con el cambio de intervalo para poder aplicar fourier&lt;br /&gt;
&lt;br /&gt;
    sN = a0 \&lt;br /&gt;
         + (ak[:, None] * np.cos(theta)).sum(axis=0) \ ### multiplica cada coeficiente con su coseno respectivo, en forma de vector por cada punto del linspace&lt;br /&gt;
         + (bk[:, None] * np.sin(theta)).sum(axis=0)   ### lo mismo para el seno&lt;br /&gt;
&lt;br /&gt;
    return sN ### devuelve la serie de fourier&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) VISUALIZACIÓN&lt;br /&gt;
# =====================================================&lt;br /&gt;
Ns = [1, 3, 5, 10, 40, 80] ### Representación python&lt;br /&gt;
&lt;br /&gt;
cols = 3&lt;br /&gt;
rows = (len(Ns) + cols - 1) // cols&lt;br /&gt;
&lt;br /&gt;
fig, axes = plt.subplots(rows, cols, figsize=(12, 3*rows))&lt;br /&gt;
axes = axes.flatten()&lt;br /&gt;
&lt;br /&gt;
for i, N in enumerate(Ns):&lt;br /&gt;
    sN = partial_sum_real_direct(N, x, fx, a=a, L=L)&lt;br /&gt;
&lt;br /&gt;
    axes[i].plot(x, fx, color='black', linewidth=2, label=&amp;quot;f(x)&amp;quot;)&lt;br /&gt;
    axes[i].plot(x, sN, color='red', linewidth=1.6, label=&amp;quot;S_N(x) (sin FFT)&amp;quot;)&lt;br /&gt;
    axes[i].set_title(f&amp;quot;N = {N}&amp;quot;)&lt;br /&gt;
    axes[i].grid(True)&lt;br /&gt;
&lt;br /&gt;
    if i == 0:&lt;br /&gt;
        axes[i].legend(loc=&amp;quot;best&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Quitar paneles vacíos&lt;br /&gt;
for j in range(i+1, len(axes)):&lt;br /&gt;
    fig.delaxes(axes[j])&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;br /&gt;
&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# CONFIG&lt;br /&gt;
# =====================================================&lt;br /&gt;
a, b = 0.0, 1.0&lt;br /&gt;
L = b - a&lt;br /&gt;
&lt;br /&gt;
M_fft = 8192&lt;br /&gt;
h_L2 = 1e-5&lt;br /&gt;
Ns = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]&lt;br /&gt;
&lt;br /&gt;
m_max = 3  # vamos a construir f0, f1, f2, f3 a mano&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 1) f0 y sus primitivas exactas f1,f2,f3&lt;br /&gt;
# =====================================================&lt;br /&gt;
def f0(x):&lt;br /&gt;
    return np.where((x &amp;gt;= 0.0) &amp;amp; (x &amp;lt; 0.5), 1.0, 0.0)&lt;br /&gt;
&lt;br /&gt;
def f1(x):&lt;br /&gt;
    # ∫0^x f0(t) dt&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, x, 0.5)&lt;br /&gt;
&lt;br /&gt;
def f2(x):&lt;br /&gt;
    # ∫0^x f1(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^2/2&lt;br /&gt;
    # x&amp;gt;=0.5: (1/2)x - 1/8&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, 0.5*x**2, 0.5*x - 0.125)&lt;br /&gt;
&lt;br /&gt;
def f3(x):&lt;br /&gt;
    # ∫0^x f2(t) dt&lt;br /&gt;
    # x&amp;lt;0.5: x^3/6&lt;br /&gt;
    # x&amp;gt;=0.5: (1/4)x^2 - (1/8)x + 1/48&lt;br /&gt;
    return np.where(x &amp;lt; 0.5, (x**3)/6.0, 0.25*x**2 - 0.125*x + (1.0/48.0))&lt;br /&gt;
&lt;br /&gt;
f_funcs = [f0, f1, f2, f3]  # lista de funciones exactas&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 2) MALLAS Y VALORES &amp;quot;TRUE&amp;quot; EN L2&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_L2 = np.arange(a, b, h_L2)&lt;br /&gt;
f_list = [f_funcs[m](x_L2) for m in range(m_max + 1)]  # f0..f3 evaluadas en x_L2&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 3) Fourier por FFT sobre una malla uniforme para coeficientes&lt;br /&gt;
#    (ojo: extensión periódica implícita de lo que haya en [0,1))&lt;br /&gt;
# =====================================================&lt;br /&gt;
x_fft = np.linspace(a, b, M_fft, endpoint=False)&lt;br /&gt;
&lt;br /&gt;
def fourier_coeffs_up_to_from_samples(fx_samples):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Devuelve coeffs_up_to(N) -&amp;gt; (a0, ak, bk) para:&lt;br /&gt;
    f(x) ~ a0 + sum_{k=1}^N [ak cos(2πk(x-a)/L) + bk sin(2πk(x-a)/L)].&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    C = np.fft.fft(fx_samples) / M_fft&lt;br /&gt;
    a0 = C[0].real&lt;br /&gt;
&lt;br /&gt;
    def coeffs_up_to(N):&lt;br /&gt;
        ck = C[1:N+1]&lt;br /&gt;
        ak = 2.0 * ck.real&lt;br /&gt;
        bk = -2.0 * ck.imag&lt;br /&gt;
        return a0, ak, bk&lt;br /&gt;
&lt;br /&gt;
    return coeffs_up_to&lt;br /&gt;
&lt;br /&gt;
def partial_sum_real(coeffs_up_to, N, xgrid):&lt;br /&gt;
    a0, ak, bk = coeffs_up_to(N)&lt;br /&gt;
    s = a0 * np.ones_like(xgrid, dtype=float)&lt;br /&gt;
    for k in range(1, N+1):&lt;br /&gt;
        ang = 2*np.pi*k*(xgrid - a)/L&lt;br /&gt;
        s += ak[k-1]*np.cos(ang) + bk[k-1]*np.sin(ang)&lt;br /&gt;
    return s&lt;br /&gt;
&lt;br /&gt;
def L2_error(f_true_vals, s_vals, xgrid):&lt;br /&gt;
    e = f_true_vals - s_vals&lt;br /&gt;
    return np.sqrt(np.trapz(e**2, xgrid))&lt;br /&gt;
&lt;br /&gt;
# Precomputamos coeffs_up_to para cada m (muestreando en x_fft)&lt;br /&gt;
coeffs_list = []&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_m_on_fft = f_funcs[m](x_fft)  # como es explícita, no hace falta interp&lt;br /&gt;
    coeffs_list.append(fourier_coeffs_up_to_from_samples(f_m_on_fft))&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 4) EXPERIMENTO: error L2 vs N para cada m&lt;br /&gt;
# =====================================================&lt;br /&gt;
plt.figure(figsize=(7,5))&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    f_true = f_list[m]&lt;br /&gt;
    coeffs_up_to = coeffs_list[m]&lt;br /&gt;
    E = []&lt;br /&gt;
    for N in Ns:&lt;br /&gt;
        sN = partial_sum_real(coeffs_up_to, N, x_L2)&lt;br /&gt;
        E.append(L2_error(f_true, sN, x_L2))&lt;br /&gt;
    plt.loglog(Ns, E, marker='o', label=f&amp;quot;m={m} (f_{m} exacta)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.grid(True, which=&amp;quot;both&amp;quot;)&lt;br /&gt;
plt.xlabel(&amp;quot;N&amp;quot;)&lt;br /&gt;
plt.ylabel(r&amp;quot;$\|f_m - S_N\|_{L^2(0,1)}$&amp;quot;)&lt;br /&gt;
plt.title(&amp;quot;Convergencia L2 vs N usando primitivas EXACTAS (sin integrar numéricamente)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
# =====================================================&lt;br /&gt;
# 5) Visualización de f_m exactas&lt;br /&gt;
# =====================================================&lt;br /&gt;
fig, axes = plt.subplots(m_max + 1, 1, figsize=(9, 2.4*(m_max+1)))&lt;br /&gt;
if m_max == 0:&lt;br /&gt;
    axes = [axes]&lt;br /&gt;
&lt;br /&gt;
for m in range(m_max + 1):&lt;br /&gt;
    axes[m].plot(x_L2, f_list[m], linewidth=1.8)&lt;br /&gt;
    axes[m].grid(True)&lt;br /&gt;
    axes[m].set_title(f&amp;quot;f_{m}(x) exacta (integración aplicada {m} veces)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&lt;br /&gt;
#nuevo código&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104295</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104295"/>
				<updated>2026-02-18T23:27:21Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Códigos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo - Paula Dopico Muñoz - Manuel Herreros Zarco.}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
T = 1.0 ### Longitud del intervalo&lt;br /&gt;
n_max = 3  # La frecuencua hasta la que pinta senos y cosenos para representar la base lineal&lt;br /&gt;
M = 3000 ### Número de puntos en X&lt;br /&gt;
&lt;br /&gt;
x = np.linspace(-T, T, M) ### Genera un vector de M puntos entre -T y T&lt;br /&gt;
&lt;br /&gt;
plt.figure(figsize=(10,5)) ### Tamaño de la gráfica, pa q sea grande o chiquita pero no afecta a los puntos&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
phi0 = (1/np.sqrt(2*T)) * np.ones_like(x) ### Genera un vector de 3000 ptos con cada uno la función cte de la basepara luego representarlo&lt;br /&gt;
plt.plot(x, phi0, linewidth=3) ### Pinta la linea generada por la función phi0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
for n in range(1, n_max + 1): ### Pinta las funciones seno y coseno asociadas a cada frecuencia en el plot&lt;br /&gt;
    phi_c = (1/np.sqrt(T)) * np.cos(n*np.pi*x/T) ### funcion coseno&lt;br /&gt;
    phi_s = (1/np.sqrt(T)) * np.sin(n*np.pi*x/T) ### funcion seno&lt;br /&gt;
    &lt;br /&gt;
    plt.plot(x, phi_c)&lt;br /&gt;
    plt.plot(x, phi_s) &lt;br /&gt;
&lt;br /&gt;
plt.title(&amp;quot;Base trigonométrica ortonormal en [-T, T]&amp;quot;) ### SIstema de representación de python&lt;br /&gt;
plt.xlabel(&amp;quot;x&amp;quot;)&lt;br /&gt;
plt.grid(True)&lt;br /&gt;
plt.tight_layout()&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104292</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104292"/>
				<updated>2026-02-18T23:25:24Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Poster */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo - Paula Dopico Muñoz - Manuel Herreros Zarco.}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPosterDefinitivo.jpeg|center|800px]]]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:FinalPosterDefinitivo.jpeg&amp;diff=104290</id>
		<title>Archivo:FinalPosterDefinitivo.jpeg</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:FinalPosterDefinitivo.jpeg&amp;diff=104290"/>
				<updated>2026-02-18T23:24:40Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104286</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104286"/>
				<updated>2026-02-18T23:23:19Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Poster */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo - Paula Dopico Muñoz - Manuel Herreros Zarco.}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:FinalPoster.jpeg||center|800px]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:FinalPoster(DPM).jpeg&amp;diff=104285</id>
		<title>Archivo:FinalPoster(DPM).jpeg</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:FinalPoster(DPM).jpeg&amp;diff=104285"/>
				<updated>2026-02-18T23:21:51Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104277</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104277"/>
				<updated>2026-02-18T23:12:51Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Poster */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo - Paula Dopico Muñoz - Manuel Herreros Zarco.}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:Series de FourierPoster(DPM).png|center|800px]]&lt;br /&gt;
&lt;br /&gt;
===Códigos===&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104276</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104276"/>
				<updated>2026-02-18T23:12:21Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Códigos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo - Paula Dopico Muñoz - Manuel Herreros Zarco.}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:Series de FourierPoster(DPM).png|miniaturadeimagen]]&lt;br /&gt;
===Códigos===&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104274</id>
		<title>Usuario:DiegoGR</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Usuario:DiegoGR&amp;diff=104274"/>
				<updated>2026-02-18T23:10:39Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: /* Series de Fourier */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier(DPM)| [[:Categoría:EDP|EDP]]|[[:Categoría:EDP25/26|2025-26]] | Diego García Raposo - Paula Dopico Muñoz - Manuel Herreros Zarco.}}&lt;br /&gt;
&lt;br /&gt;
==Series de Fourier==&lt;br /&gt;
===Poster===&lt;br /&gt;
[[Archivo:Series de FourierPoster(DPM).png|miniaturadeimagen]]&lt;br /&gt;
===Códigos===&lt;br /&gt;
[[Archivo:Codigos Trabajo EDP.ipynb|miniaturadeimagen]]&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:Codigos_Trabajo_EDP.ipynb&amp;diff=104272</id>
		<title>Archivo:Codigos Trabajo EDP.ipynb</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:Codigos_Trabajo_EDP.ipynb&amp;diff=104272"/>
				<updated>2026-02-18T23:09:45Z</updated>
		
		<summary type="html">&lt;p&gt;DiegoGR: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>DiegoGR</name></author>	</entry>

	</feed>