<?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=Nacho</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=Nacho"/>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/wiki/Especial:Contribuciones/Nacho"/>
		<updated>2026-04-29T00:01:23Z</updated>
		<subtitle>Contribuciones del usuario</subtitle>
		<generator>MediaWiki 1.26.2</generator>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86284</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86284"/>
				<updated>2025-11-16T22:16:28Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Poster MNEDP 2025 CAD 2.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
También es posible [https://objectstorage.eu-madrid-3.oraclecloud.com/n/axfzuuzt6hgr/b/bucket-20251109-1118/o/Poster_MNEDP.pdf ver el póster en PDF a resolución completa]. Se puede acceder a los contenidos del código QR mediante [https://upm365-my.sharepoint.com/:f:/g/personal/ignacio_mcerezo_alumnos_upm_es/ErKozPkziC1Libi_AA5ymBcBUvtgf0WEWuWRrldhSUmfuA?e=ADGVcV este enlace].&lt;br /&gt;
&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: calculate_con_mesh_params.m ==&lt;br /&gt;
Este código se encarga de escoger unos parámetros concretos para el mallado a partir de un valor concreto de &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = calculate_con_mesh_params(h, R, r1)&lt;br /&gt;
    %calcula los parámetros de generate_mesh necesarios para conseguir una&lt;br /&gt;
    %cierta &amp;quot;h&amp;quot; (es un poco heurístico e impreciso, pero funciona!)&lt;br /&gt;
    circum_inner = 2*pi*r1;&lt;br /&gt;
    circum_outer = 2*pi*R;&lt;br /&gt;
&lt;br /&gt;
    %divisiones angulares&lt;br /&gt;
    ntheta_inner = max(3, ceil(circum_inner / h));&lt;br /&gt;
    ntheta_outer = max(3, ceil(circum_outer / h));&lt;br /&gt;
&lt;br /&gt;
    %divisiones de tipo anillo&lt;br /&gt;
    nr_inner = max(1, ceil(r1 / h));&lt;br /&gt;
    nr_outer = max(1, ceil((R - r1) / h));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; concreta y una &amp;quot;excentricidad&amp;quot; dada.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
Este código representa el mallado que hemos generado con las funciones anteriores, diferenciando en las dos regiones &amp;lt;math&amp;gt;\Omega_1&amp;lt;/math&amp;gt; y &amp;lt;math&amp;gt;\Omega_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
Este código representa la solución que calculan los códigos posteriores.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
Este código ensambla el sistema lineal que resulta del método de elementos finitos.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
La función principal, aplica las funciones anteriores a un problema concreto, generando el mallado y usándolo con una &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; concreta, definida en el mismo código.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:Poster_MNEDP_2025_CAD_2.jpg&amp;diff=86283</id>
		<title>Archivo:Poster MNEDP 2025 CAD 2.jpg</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:Poster_MNEDP_2025_CAD_2.jpg&amp;diff=86283"/>
				<updated>2025-11-16T22:15:23Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: Segunda versión de Poster MNEDP 2025 CAD.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Segunda versión de Poster MNEDP 2025 CAD.jpg&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86282</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86282"/>
				<updated>2025-11-16T21:58:34Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Poster MNEDP 2025 CAD.jpg|1000px]]&lt;br /&gt;
&lt;br /&gt;
También es posible [https://objectstorage.eu-madrid-3.oraclecloud.com/n/axfzuuzt6hgr/b/bucket-20251109-1118/o/Poster_MNEDP_2025_CAD.pdf ver el póster en PDF a resolución completa]. Se puede acceder a los contenidos del código QR mediante [https://upm365-my.sharepoint.com/:f:/g/personal/ignacio_mcerezo_alumnos_upm_es/ErKozPkziC1Libi_AA5ymBcBUvtgf0WEWuWRrldhSUmfuA?e=ADGVcV este enlace].&lt;br /&gt;
&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: calculate_con_mesh_params.m ==&lt;br /&gt;
Este código se encarga de escoger unos parámetros concretos para el mallado a partir de un valor concreto de &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = calculate_con_mesh_params(h, R, r1)&lt;br /&gt;
    %calcula los parámetros de generate_mesh necesarios para conseguir una&lt;br /&gt;
    %cierta &amp;quot;h&amp;quot; (es un poco heurístico e impreciso, pero funciona!)&lt;br /&gt;
    circum_inner = 2*pi*r1;&lt;br /&gt;
    circum_outer = 2*pi*R;&lt;br /&gt;
&lt;br /&gt;
    %divisiones angulares&lt;br /&gt;
    ntheta_inner = max(3, ceil(circum_inner / h));&lt;br /&gt;
    ntheta_outer = max(3, ceil(circum_outer / h));&lt;br /&gt;
&lt;br /&gt;
    %divisiones de tipo anillo&lt;br /&gt;
    nr_inner = max(1, ceil(r1 / h));&lt;br /&gt;
    nr_outer = max(1, ceil((R - r1) / h));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; concreta y una &amp;quot;excentricidad&amp;quot; dada.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
Este código representa el mallado que hemos generado con las funciones anteriores, diferenciando en las dos regiones &amp;lt;math&amp;gt;\Omega_1&amp;lt;/math&amp;gt; y &amp;lt;math&amp;gt;\Omega_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
Este código representa la solución que calculan los códigos posteriores.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
Este código ensambla el sistema lineal que resulta del método de elementos finitos.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
La función principal, aplica las funciones anteriores a un problema concreto, generando el mallado y usándolo con una &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; concreta, definida en el mismo código.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86281</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86281"/>
				<updated>2025-11-16T21:55:32Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Poster MNEDP 2025 CAD.jpg]]&lt;br /&gt;
&lt;br /&gt;
También es posible [https://objectstorage.eu-madrid-3.oraclecloud.com/n/axfzuuzt6hgr/b/bucket-20251109-1118/o/Poster_MNEDP_2025_CAD.pdf ver el póster en PDF a resolución completa].&lt;br /&gt;
&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: calculate_con_mesh_params.m ==&lt;br /&gt;
Este código se encarga de escoger unos parámetros concretos para el mallado a partir de un valor concreto de &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = calculate_con_mesh_params(h, R, r1)&lt;br /&gt;
    %calcula los parámetros de generate_mesh necesarios para conseguir una&lt;br /&gt;
    %cierta &amp;quot;h&amp;quot; (es un poco heurístico e impreciso, pero funciona!)&lt;br /&gt;
    circum_inner = 2*pi*r1;&lt;br /&gt;
    circum_outer = 2*pi*R;&lt;br /&gt;
&lt;br /&gt;
    %divisiones angulares&lt;br /&gt;
    ntheta_inner = max(3, ceil(circum_inner / h));&lt;br /&gt;
    ntheta_outer = max(3, ceil(circum_outer / h));&lt;br /&gt;
&lt;br /&gt;
    %divisiones de tipo anillo&lt;br /&gt;
    nr_inner = max(1, ceil(r1 / h));&lt;br /&gt;
    nr_outer = max(1, ceil((R - r1) / h));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; concreta y una &amp;quot;excentricidad&amp;quot; dada.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
Este código representa el mallado que hemos generado con las funciones anteriores, diferenciando en las dos regiones &amp;lt;math&amp;gt;\Omega_1&amp;lt;/math&amp;gt; y &amp;lt;math&amp;gt;\Omega_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
Este código representa la solución que calculan los códigos posteriores.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
Este código ensambla el sistema lineal que resulta del método de elementos finitos.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
La función principal, aplica las funciones anteriores a un problema concreto, generando el mallado y usándolo con una &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; concreta, definida en el mismo código.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86280</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86280"/>
				<updated>2025-11-16T21:55:19Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
&lt;br /&gt;
[Archivo:Poster MNEDP 2025 CAD.jpg]&lt;br /&gt;
&lt;br /&gt;
También es posible [https://objectstorage.eu-madrid-3.oraclecloud.com/n/axfzuuzt6hgr/b/bucket-20251109-1118/o/Poster_MNEDP_2025_CAD.pdf ver el póster en PDF a resolución completa].&lt;br /&gt;
&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: calculate_con_mesh_params.m ==&lt;br /&gt;
Este código se encarga de escoger unos parámetros concretos para el mallado a partir de un valor concreto de &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = calculate_con_mesh_params(h, R, r1)&lt;br /&gt;
    %calcula los parámetros de generate_mesh necesarios para conseguir una&lt;br /&gt;
    %cierta &amp;quot;h&amp;quot; (es un poco heurístico e impreciso, pero funciona!)&lt;br /&gt;
    circum_inner = 2*pi*r1;&lt;br /&gt;
    circum_outer = 2*pi*R;&lt;br /&gt;
&lt;br /&gt;
    %divisiones angulares&lt;br /&gt;
    ntheta_inner = max(3, ceil(circum_inner / h));&lt;br /&gt;
    ntheta_outer = max(3, ceil(circum_outer / h));&lt;br /&gt;
&lt;br /&gt;
    %divisiones de tipo anillo&lt;br /&gt;
    nr_inner = max(1, ceil(r1 / h));&lt;br /&gt;
    nr_outer = max(1, ceil((R - r1) / h));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; concreta y una &amp;quot;excentricidad&amp;quot; dada.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
Este código representa el mallado que hemos generado con las funciones anteriores, diferenciando en las dos regiones &amp;lt;math&amp;gt;\Omega_1&amp;lt;/math&amp;gt; y &amp;lt;math&amp;gt;\Omega_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
Este código representa la solución que calculan los códigos posteriores.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
Este código ensambla el sistema lineal que resulta del método de elementos finitos.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
La función principal, aplica las funciones anteriores a un problema concreto, generando el mallado y usándolo con una &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; concreta, definida en el mismo código.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:Poster_MNEDP_2025_CAD.jpg&amp;diff=86279</id>
		<title>Archivo:Poster MNEDP 2025 CAD.jpg</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:Poster_MNEDP_2025_CAD.jpg&amp;diff=86279"/>
				<updated>2025-11-16T21:53:37Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: Póster del trabajo &amp;quot;Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN&amp;quot; de Métodos Numéricos en EDP impartida por Carlos Castro y Maria Luisa Rapún en el Grado en Matemáticas. Trabajo realizado por el grupo CAD. Curso 2025/2026.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Póster del trabajo &amp;quot;Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN&amp;quot; de Métodos Numéricos en EDP impartida por Carlos Castro y Maria Luisa Rapún en el Grado en Matemáticas. Trabajo realizado por el grupo CAD. Curso 2025/2026.&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86274</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86274"/>
				<updated>2025-11-16T21:42:30Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: /* Póster del Trabajo */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: calculate_con_mesh_params.m ==&lt;br /&gt;
Este código se encarga de escoger unos parámetros concretos para el mallado a partir de un valor concreto de &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = calculate_con_mesh_params(h, R, r1)&lt;br /&gt;
    %calcula los parámetros de generate_mesh necesarios para conseguir una&lt;br /&gt;
    %cierta &amp;quot;h&amp;quot; (es un poco heurístico e impreciso, pero funciona!)&lt;br /&gt;
    circum_inner = 2*pi*r1;&lt;br /&gt;
    circum_outer = 2*pi*R;&lt;br /&gt;
&lt;br /&gt;
    %divisiones angulares&lt;br /&gt;
    ntheta_inner = max(3, ceil(circum_inner / h));&lt;br /&gt;
    ntheta_outer = max(3, ceil(circum_outer / h));&lt;br /&gt;
&lt;br /&gt;
    %divisiones de tipo anillo&lt;br /&gt;
    nr_inner = max(1, ceil(r1 / h));&lt;br /&gt;
    nr_outer = max(1, ceil((R - r1) / h));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; concreta y una &amp;quot;excentricidad&amp;quot; dada.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
Este código representa el mallado que hemos generado con las funciones anteriores, diferenciando en las dos regiones &amp;lt;math&amp;gt;\Omega_1&amp;lt;/math&amp;gt; y &amp;lt;math&amp;gt;\Omega_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
Este código representa la solución que calculan los códigos posteriores.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
Este código ensambla el sistema lineal que resulta del método de elementos finitos.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
La función principal, aplica las funciones anteriores a un problema concreto, generando el mallado y usándolo con una &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; concreta, definida en el mismo código.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86272</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86272"/>
				<updated>2025-11-16T21:41:26Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: /* Póster del Trabajo */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
[https://objectstorage.eu-madrid-3.oraclecloud.com/n/axfzuuzt6hgr/b/bucket-20251109-1118/o/Poster_MNEDP.pdf Ver póster en PDF]&lt;br /&gt;
&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: calculate_con_mesh_params.m ==&lt;br /&gt;
Este código se encarga de escoger unos parámetros concretos para el mallado a partir de un valor concreto de &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = calculate_con_mesh_params(h, R, r1)&lt;br /&gt;
    %calcula los parámetros de generate_mesh necesarios para conseguir una&lt;br /&gt;
    %cierta &amp;quot;h&amp;quot; (es un poco heurístico e impreciso, pero funciona!)&lt;br /&gt;
    circum_inner = 2*pi*r1;&lt;br /&gt;
    circum_outer = 2*pi*R;&lt;br /&gt;
&lt;br /&gt;
    %divisiones angulares&lt;br /&gt;
    ntheta_inner = max(3, ceil(circum_inner / h));&lt;br /&gt;
    ntheta_outer = max(3, ceil(circum_outer / h));&lt;br /&gt;
&lt;br /&gt;
    %divisiones de tipo anillo&lt;br /&gt;
    nr_inner = max(1, ceil(r1 / h));&lt;br /&gt;
    nr_outer = max(1, ceil((R - r1) / h));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; concreta y una &amp;quot;excentricidad&amp;quot; dada.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
Este código representa el mallado que hemos generado con las funciones anteriores, diferenciando en las dos regiones &amp;lt;math&amp;gt;\Omega_1&amp;lt;/math&amp;gt; y &amp;lt;math&amp;gt;\Omega_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
Este código representa la solución que calculan los códigos posteriores.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
Este código ensambla el sistema lineal que resulta del método de elementos finitos.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
La función principal, aplica las funciones anteriores a un problema concreto, generando el mallado y usándolo con una &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; concreta, definida en el mismo código.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86270</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86270"/>
				<updated>2025-11-16T21:40:37Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
&amp;lt;iframe &lt;br /&gt;
    src=&amp;quot;https://objectstorage.eu-madrid-3.oraclecloud.com/n/axfzuuzt6hgr/b/bucket-20251109-1118/o/Poster_MNEDP.pdf&amp;quot; &lt;br /&gt;
    width=&amp;quot;100%&amp;quot; &lt;br /&gt;
    height=&amp;quot;800px&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;/iframe&amp;gt;&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: calculate_con_mesh_params.m ==&lt;br /&gt;
Este código se encarga de escoger unos parámetros concretos para el mallado a partir de un valor concreto de &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = calculate_con_mesh_params(h, R, r1)&lt;br /&gt;
    %calcula los parámetros de generate_mesh necesarios para conseguir una&lt;br /&gt;
    %cierta &amp;quot;h&amp;quot; (es un poco heurístico e impreciso, pero funciona!)&lt;br /&gt;
    circum_inner = 2*pi*r1;&lt;br /&gt;
    circum_outer = 2*pi*R;&lt;br /&gt;
&lt;br /&gt;
    %divisiones angulares&lt;br /&gt;
    ntheta_inner = max(3, ceil(circum_inner / h));&lt;br /&gt;
    ntheta_outer = max(3, ceil(circum_outer / h));&lt;br /&gt;
&lt;br /&gt;
    %divisiones de tipo anillo&lt;br /&gt;
    nr_inner = max(1, ceil(r1 / h));&lt;br /&gt;
    nr_outer = max(1, ceil((R - r1) / h));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; concreta y una &amp;quot;excentricidad&amp;quot; dada.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
Este código representa el mallado que hemos generado con las funciones anteriores, diferenciando en las dos regiones &amp;lt;math&amp;gt;\Omega_1&amp;lt;/math&amp;gt; y &amp;lt;math&amp;gt;\Omega_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
Este código representa la solución que calculan los códigos posteriores.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
Este código ensambla el sistema lineal que resulta del método de elementos finitos.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
La función principal, aplica las funciones anteriores a un problema concreto, generando el mallado y usándolo con una &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; concreta, definida en el mismo código.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86259</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86259"/>
				<updated>2025-11-16T20:27:32Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
Por ahora no está! (carita triste)&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: calculate_con_mesh_params.m ==&lt;br /&gt;
Este código se encarga de escoger unos parámetros concretos para el mallado a partir de un valor concreto de &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = calculate_con_mesh_params(h, R, r1)&lt;br /&gt;
    %calcula los parámetros de generate_mesh necesarios para conseguir una&lt;br /&gt;
    %cierta &amp;quot;h&amp;quot; (es un poco heurístico e impreciso, pero funciona!)&lt;br /&gt;
    circum_inner = 2*pi*r1;&lt;br /&gt;
    circum_outer = 2*pi*R;&lt;br /&gt;
&lt;br /&gt;
    %divisiones angulares&lt;br /&gt;
    ntheta_inner = max(3, ceil(circum_inner / h));&lt;br /&gt;
    ntheta_outer = max(3, ceil(circum_outer / h));&lt;br /&gt;
&lt;br /&gt;
    %divisiones de tipo anillo&lt;br /&gt;
    nr_inner = max(1, ceil(r1 / h));&lt;br /&gt;
    nr_outer = max(1, ceil((R - r1) / h));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; concreta y una &amp;quot;excentricidad&amp;quot; dada.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
Este código representa el mallado que hemos generado con las funciones anteriores, diferenciando en las dos regiones &amp;lt;math&amp;gt;\Omega_1&amp;lt;/math&amp;gt; y &amp;lt;math&amp;gt;\Omega_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
Este código representa la solución que calculan los códigos posteriores.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
Este código ensambla el sistema lineal que resulta del método de elementos finitos.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
La función principal, aplica las funciones anteriores a un problema concreto, generando el mallado y usándolo con una &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; concreta, definida en el mismo código.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86258</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86258"/>
				<updated>2025-11-16T20:25:53Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoMNEDP | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
Por ahora no está! (carita triste)&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: calculate_con_mesh_params.m ==&lt;br /&gt;
Este código se encarga de escoger unos parámetros concretos para el mallado a partir de un valor concreto de &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = calculate_con_mesh_params(h, R, r1)&lt;br /&gt;
    %calcula los parámetros de generate_mesh necesarios para conseguir una&lt;br /&gt;
    %cierta &amp;quot;h&amp;quot; (es un poco heurístico e impreciso, pero funciona!)&lt;br /&gt;
    circum_inner = 2*pi*r1;&lt;br /&gt;
    circum_outer = 2*pi*R;&lt;br /&gt;
&lt;br /&gt;
    %divisiones angulares&lt;br /&gt;
    ntheta_inner = max(3, ceil(circum_inner / h));&lt;br /&gt;
    ntheta_outer = max(3, ceil(circum_outer / h));&lt;br /&gt;
&lt;br /&gt;
    %divisiones de tipo anillo&lt;br /&gt;
    nr_inner = max(1, ceil(r1 / h));&lt;br /&gt;
    nr_outer = max(1, ceil((R - r1) / h));&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; concreta y una &amp;quot;excentricidad&amp;quot; dada.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
Este código representa el mallado que hemos generado con las funciones anteriores, diferenciando en las dos regiones &amp;lt;math&amp;gt;\Omega_1&amp;lt;/math&amp;gt; y &amp;lt;math&amp;gt;\Omega_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
Este código representa la solución que calculan los códigos posteriores.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
Este código ensambla el sistema lineal que resulta del método de elementos finitos.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
La función principal, aplica las funciones anteriores a un problema concreto, generando el mallado y usándolo con una &amp;lt;math&amp;gt;f&amp;lt;/math&amp;gt; concreta, definida en el mismo código.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86257</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86257"/>
				<updated>2025-11-16T20:22:16Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: /* Código: generate_mesh.m */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoMNEDP | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
Por ahora no está! (carita triste)&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; concreta y una &amp;quot;excentricidad&amp;quot; dada.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86256</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86256"/>
				<updated>2025-11-16T20:21:55Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: /* Código: generate_mesh.m */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoMNEDP | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
Por ahora no está! (carita triste)&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; concreta.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86254</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86254"/>
				<updated>2025-11-16T20:21:19Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: /* Código: generate_mesh.m */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoMNEDP | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
Por ahora no está! (carita triste)&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
Este código se encarga de generar el mallado para una &amp;lt;math&amp;gt;h&amp;lt;\math&amp;gt; concreta.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86253</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86253"/>
				<updated>2025-11-16T20:20:11Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: /* Código: make_concentric_mesh.m */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoMNEDP | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
Por ahora no está! (carita triste)&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
Esta función se encarga de generar el mallado.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86252</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86252"/>
				<updated>2025-11-16T20:17:19Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoMNEDP | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
Por ahora no está! (carita triste)&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
function generate_mesh(h, name, exc)&lt;br /&gt;
    %calculamos los valores que nos dan esta h mínima&lt;br /&gt;
    [ntheta_inner, ntheta_outer, nr_inner, nr_outer] = ...&lt;br /&gt;
        calculate_con_mesh_params(h, 1.0, 0.95);&lt;br /&gt;
    &lt;br /&gt;
    ntheta_outer = max([3, ntheta_inner, ntheta_outer]);&lt;br /&gt;
    ntheta_inner = ntheta_outer;&lt;br /&gt;
    &lt;br /&gt;
    %generamos el mallado (y se guarda)&lt;br /&gt;
    make_concentric_mesh( ...&lt;br /&gt;
        1.0, 0.95, ntheta_outer, ntheta_inner, nr_inner, nr_outer, ...&lt;br /&gt;
        exc, name + &amp;quot;.mat&amp;quot;);&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_mesh(mesh, h)&lt;br /&gt;
    %representación del mallado en dos partes Omega_1 y Omega_2&lt;br /&gt;
&lt;br /&gt;
    %cargamos cada parte del mallado&lt;br /&gt;
    T = mesh.cells;&lt;br /&gt;
    P = mesh.points;&lt;br /&gt;
    R = mesh.regions;&lt;br /&gt;
    &lt;br /&gt;
    % Índices de triángulos de cada región&lt;br /&gt;
    idx1 = (R == 1);&lt;br /&gt;
    idx2 = (R == 2);&lt;br /&gt;
    &lt;br /&gt;
    figure('Position',[100 100 900 700]); hold on;&lt;br /&gt;
    &lt;br /&gt;
    %hacemos un triplot de los triángulos de Omega_1 (a un color)&lt;br /&gt;
    triplot(T(idx1,:), P(:,1), P(:,2), color = '#80B3FF');&lt;br /&gt;
    %hacemos otro triplot de los triángulos de Omega_2 (a otro color)&lt;br /&gt;
    triplot(T(idx2,:), P(:,1), P(:,2), 'blue');&lt;br /&gt;
    &lt;br /&gt;
    title(&amp;quot;Representación del mallado por regiones&amp;quot;);&lt;br /&gt;
    xlabel('X');&lt;br /&gt;
    ylabel('Y');&lt;br /&gt;
    axis equal;&lt;br /&gt;
    saveas(gcf, &amp;quot;mesh_representation h=&amp;quot;+num2str(h)+&amp;quot;.pdf&amp;quot;);&lt;br /&gt;
    hold off;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function plot_solution(P, T, u, elev, azim, levels, prefijo)&lt;br /&gt;
    &lt;br /&gt;
    %Representamos la superficie&lt;br /&gt;
    figure('Name','Rerepsetnación como superficie');&lt;br /&gt;
    %hacemos un trisurf sin marcar los triángulos (queda feo si hay muchos)&lt;br /&gt;
    trisurf(T, P(:,1), P(:,2), u, 'EdgeColor','none');&lt;br /&gt;
    xlabel('x'); ylabel('y'); zlabel('u');&lt;br /&gt;
    %los parámetros de vista iniciales son parámetros&lt;br /&gt;
    view(elev, azim);&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (superficie 3D)');&lt;br /&gt;
&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_surface.png&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    %otra figura para el mapa de calor de los niveles&lt;br /&gt;
    figure('Name','Representación como contorno');&lt;br /&gt;
&lt;br /&gt;
    %como no podemos hacerlo circular (no sabemos), lo hacemos cuadrado&lt;br /&gt;
    xg = linspace(min(P(:,1)), max(P(:,1)), 300);&lt;br /&gt;
    yg = linspace(min(P(:,2)), max(P(:,2)), 300);&lt;br /&gt;
&lt;br /&gt;
    [X,Y] = meshgrid(xg, yg);&lt;br /&gt;
    &lt;br /&gt;
    %función para interpolar los datos de los nodos al resto del mallado&lt;br /&gt;
    Fint = scatteredInterpolant(P(:,1), P(:,2), u, 'natural');&lt;br /&gt;
    Ugrid = Fint(X,Y);&lt;br /&gt;
    &lt;br /&gt;
    %contornos (sin líneas en los bordes)&lt;br /&gt;
    contourf(X, Y, Ugrid, levels, 'LineColor','none');&lt;br /&gt;
&lt;br /&gt;
    axis equal; axis tight;&lt;br /&gt;
    xlabel('x'); ylabel('y');&lt;br /&gt;
    colormap('jet');&lt;br /&gt;
    colorbar;&lt;br /&gt;
    title('Solución FEM (contorno)');&lt;br /&gt;
    %lo guardamos&lt;br /&gt;
    saveas(gcf, prefijo + &amp;quot;_contour.png&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [A, F, P, T] = assemble_system(mesh_path, f_rhs)&lt;br /&gt;
&lt;br /&gt;
    data = load(mesh_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
    P = data.points;    % Nx2&lt;br /&gt;
    T = data.cells;     % Mx3&lt;br /&gt;
    R = data.regions;   % Mx1 (región de cada elemento)&lt;br /&gt;
&lt;br /&gt;
    N = size(P, 1);&lt;br /&gt;
    M = size(T, 1);&lt;br /&gt;
&lt;br /&gt;
    %conductividades&lt;br /&gt;
    sigma1 = 0.33;   % cerebro&lt;br /&gt;
    sigma2 = 0.16;   % cráneo&lt;br /&gt;
&lt;br /&gt;
    %matriz global y vector de cargas&lt;br /&gt;
    A = sparse(N, N);&lt;br /&gt;
    F = zeros(N, 1);&lt;br /&gt;
&lt;br /&gt;
    %bucle sobre elementos&lt;br /&gt;
    for k = 1:M&lt;br /&gt;
        nodes  = T(k, :);        %índices de los nodos del triángulo, 1x3&lt;br /&gt;
        coords = P(nodes, :);    %coordenada, 3x2&lt;br /&gt;
&lt;br /&gt;
        x1 = coords(1,1); &lt;br /&gt;
        y1 = coords(1,2);&lt;br /&gt;
    &lt;br /&gt;
        x2 = coords(2,1); &lt;br /&gt;
        y2 = coords(2,2);&lt;br /&gt;
    &lt;br /&gt;
        x3 = coords(3,1); &lt;br /&gt;
        y3 = coords(3,2);&lt;br /&gt;
    &lt;br /&gt;
        area = 0.5 * abs( (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1) );&lt;br /&gt;
&lt;br /&gt;
        % Escogemos sigma según región&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            sigma = sigma1;&lt;br /&gt;
        else&lt;br /&gt;
            sigma = sigma2;&lt;br /&gt;
        end&lt;br /&gt;
        &lt;br /&gt;
        %matriz BK (igual que en clase)&lt;br /&gt;
        BK = [coords(2,1) - coords(1,1), coords(3,1) - coords(1,1);&lt;br /&gt;
                       coords(2,2) - coords(1,2), coords(3,2) - coords(1,2)];&lt;br /&gt;
       &lt;br /&gt;
        %matriz de rigidez local (igual que en clase, pero en otra función&lt;br /&gt;
        %para que sea más limpio)&lt;br /&gt;
        Ke = local_stiffness_L(2*area, BK, sigma);&lt;br /&gt;
&lt;br /&gt;
        %calculamos la aportación al vector de cargas diferenciando entre&lt;br /&gt;
        %la región interior y la región exterior&lt;br /&gt;
        if R(k) == 1&lt;br /&gt;
            %hacemos la media de la f, igual que en clase&lt;br /&gt;
            fk = 1/3 * (f_rhs(x1,y1) + f_rhs(x2,y2)+ f_rhs(x3,y3));&lt;br /&gt;
            fe = local_load_L(BK, fk);&lt;br /&gt;
        else&lt;br /&gt;
            fe = zeros(3, 1);&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        % Añadimos las aportaciones al vector de carga y a la matriz de&lt;br /&gt;
        % rigidez de este triángulo&lt;br /&gt;
        F(nodes) = F(nodes) + fe;&lt;br /&gt;
        A(nodes, nodes) = A(nodes, nodes) + Ke;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function Ke = local_stiffness_L(alpha, BK, sigma)&lt;br /&gt;
    % Matriz de rigidez local&lt;br /&gt;
    % Matriz de deformación Ck = inv(BK) @ inv(BK).T&lt;br /&gt;
    invBk = inv(BK);&lt;br /&gt;
&lt;br /&gt;
    Ck = invBk*invBk';&lt;br /&gt;
&lt;br /&gt;
    % Matrices L&lt;br /&gt;
    Lxx = 0.5 * [1, -1, 0; -1, 1, 0; 0, 0, 0];&lt;br /&gt;
    Lyy = 0.5 * [1, 0, -1; 0, 0, 0; -1, 0, 1];&lt;br /&gt;
    Lxy = 0.5 * [1, -1, 0; 0, 0, 0; -1, 1, 0];&lt;br /&gt;
&lt;br /&gt;
    % Matriz local de rigidez&lt;br /&gt;
    LK = Ck(1,1)*Lxx + Ck(1,2)*(Lxy + Lxy') + Ck(2,2)*Lyy;&lt;br /&gt;
    Ke = sigma * 0.5 * abs(alpha) * LK;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function fe = local_load_L(BK, fK)&lt;br /&gt;
    %vector de carga local de 3x1 usando:&lt;br /&gt;
    % fe = fK * |det(BK)| * ell0&lt;br /&gt;
    %donde ell0 = [1/6; 1/6; 1/6] (apuntes)&lt;br /&gt;
&lt;br /&gt;
    ell0 = [1/6; 1/6; 1/6];&lt;br /&gt;
    area2 = abs(det(BK));  % |det(BK)| = 2 * area&lt;br /&gt;
    fe = fK * area2 * ell0;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
%escogemos una h y un valor de &amp;quot;excentricidad&amp;quot;&lt;br /&gt;
h = 0.025;&lt;br /&gt;
%esta &amp;quot;excentricidad&amp;quot; no es rigurosa, es simplemente un parámetro para&lt;br /&gt;
%regular cómo de achatada es la elipse de nuestra región, ¡no todas las&lt;br /&gt;
%cabezas son iguales!&lt;br /&gt;
excentricidad = 1; &lt;br /&gt;
&lt;br /&gt;
% generamos el mallado&lt;br /&gt;
mesh_name = &amp;quot;head_mesh&amp;quot;;&lt;br /&gt;
generate_mesh(h, mesh_name, excentricidad)&lt;br /&gt;
mesh_path = mesh_name + &amp;quot;.mat&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%cargamos el mallado desde el archivo&lt;br /&gt;
mesh = load(&amp;quot;head_mesh.mat&amp;quot;, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
plot_mesh(mesh, h)&lt;br /&gt;
&lt;br /&gt;
%parámetros para el doble dipolo&lt;br /&gt;
%intensidad del primer dipolo suave&lt;br /&gt;
A1 = 2; &lt;br /&gt;
%intensidad del segundo dipolo suave&lt;br /&gt;
A2 = -2;&lt;br /&gt;
%&amp;quot;radio&amp;quot; inverso del dipolo&lt;br /&gt;
TD = 0.02;&lt;br /&gt;
&lt;br /&gt;
%definimos la función f&lt;br /&gt;
function val = f_rhslack(x, y, A1, A2, TD)&lt;br /&gt;
    % % Fuente intracraneal f(x,y).&lt;br /&gt;
    % val = x.^2 - y.^2 ;&lt;br /&gt;
&lt;br /&gt;
    x0 = 0; y0 = 0;&lt;br /&gt;
    val = A1 * (x./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
    % x0 = -0.1; y0 = -0.1;&lt;br /&gt;
    % val = val + A2 * (y./ TD).*exp(-((x-x0).^2 + (y-y0).^2) / TD);&lt;br /&gt;
end&lt;br /&gt;
%handle de función con los valores de A1, A2 y TD definidos arriba&lt;br /&gt;
f_rhs = @(x,y) f_rhslack(x,y, A1, A2, TD);&lt;br /&gt;
&lt;br /&gt;
%ensamblamos el sistema&lt;br /&gt;
[A, F, P, T] = assemble_system(mesh_path, f_rhs);&lt;br /&gt;
&lt;br /&gt;
% Resolución del sistema&lt;br /&gt;
u = A \ F;&lt;br /&gt;
&lt;br /&gt;
name = &amp;quot;SolucionFEMcabeza&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
%Representación de la solución&lt;br /&gt;
plot_solution(P, T, u, 35, -60, 30, name)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86251</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86251"/>
				<updated>2025-11-16T20:15:26Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: /* Código: make_concentric_mesh.m */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoMNEDP | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
Por ahora no está! (carita triste)&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;MATLAB&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86250</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86250"/>
				<updated>2025-11-16T20:15:05Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: Añado la primera función a ver si se ve bien&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoMNEDP | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
Por ahora no está! (carita triste)&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
== Código: make_concentric_mesh.m ==&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;matlab&amp;quot;&amp;gt;&lt;br /&gt;
function [points, cells, regions] = make_concentric_mesh( ...&lt;br /&gt;
        R, r1, ntheta_outer, ntheta_inner, nr_inner, nr_outer, exc, save_path)&lt;br /&gt;
&lt;br /&gt;
    %esta función genera el mallado de la elipse añadiendo radios y elipses&lt;br /&gt;
    %semejantes más pequeñas interiores (anillos elípticos)&lt;br /&gt;
&lt;br /&gt;
    % exc = semieje vertical / semieje horizontal&lt;br /&gt;
    &lt;br /&gt;
&lt;br /&gt;
    % radios&lt;br /&gt;
    r_inner = linspace(0, r1, nr_inner + 1);&lt;br /&gt;
    r_outer = linspace(r1, R, nr_outer + 1);&lt;br /&gt;
    radii   = [r_inner, r_outer(2:end)];&lt;br /&gt;
    k_if    = nr_inner;  % índice de la circunferencia interfaz&lt;br /&gt;
    n_rings = numel(radii);&lt;br /&gt;
&lt;br /&gt;
    % listas para guardar los datos&lt;br /&gt;
    points = [];&lt;br /&gt;
    %como diferentes anillos tienen diferentes tamaños (los exteriores y&lt;br /&gt;
    %los interiores) no nos vale con un vector/array, así que usamos celdas&lt;br /&gt;
    %  (más parecido a una lista de Python)&lt;br /&gt;
    ring_nodes = cell(1, n_rings);&lt;br /&gt;
    %esto genera una secuencia de celdas 1xn_rings, que contendrá los&lt;br /&gt;
    %índices de los nodos de nuestros anillos&lt;br /&gt;
&lt;br /&gt;
    % k = 0 es el centro (origen)&lt;br /&gt;
    points = [0 0];&lt;br /&gt;
    ring_nodes{1} = 1;&lt;br /&gt;
    &lt;br /&gt;
    %ángulos&lt;br /&gt;
    thetas_outer = linspace(0, 2*pi, ntheta_outer+1);&lt;br /&gt;
    thetas_outer(end) = [];&lt;br /&gt;
    thetas_inner = linspace(0, 2*pi, ntheta_inner+1);&lt;br /&gt;
    thetas_inner(end) = [];&lt;br /&gt;
&lt;br /&gt;
    % anillos interiores&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_inner);&lt;br /&gt;
        % escalado vertical (exc)&lt;br /&gt;
        y = exc * r * sin(thetas_inner);   &lt;br /&gt;
        &lt;br /&gt;
        %guaradamos los puntos y los nodos de este anillo&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_inner - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % anillos exteriores&lt;br /&gt;
    for k = k_if+1:n_rings&lt;br /&gt;
        r = radii(k);&lt;br /&gt;
        x = r * cos(thetas_outer);&lt;br /&gt;
        %escalado horizontal&lt;br /&gt;
        y = exc * r * sin(thetas_outer);  &lt;br /&gt;
&lt;br /&gt;
        start_idx = size(points,1) + 1;&lt;br /&gt;
        pts = [x(:), y(:)];&lt;br /&gt;
        points = [points; pts];&lt;br /&gt;
        ring_nodes{k} = start_idx : (start_idx + ntheta_outer - 1);&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación: recorremos los anillos, que tienen el mismo número de&lt;br /&gt;
    % puntos cada uno, tomando dos nodos del anillo interior y sus dos&lt;br /&gt;
    % corrrespondientes del anillo esterior, formamos un cuadrilátero y lo&lt;br /&gt;
    % dividimos en dos, lo que genera una triangulación.&lt;br /&gt;
    cells = [];&lt;br /&gt;
    regions = [];&lt;br /&gt;
&lt;br /&gt;
    % 1. &amp;quot;estrella&amp;quot; interior (emanan del origen)&lt;br /&gt;
    for j = 1:ntheta_inner&lt;br /&gt;
        a = ring_nodes{1}(1);&lt;br /&gt;
        b = ring_nodes{2}(j);&lt;br /&gt;
        c = ring_nodes{2}(mod(j,ntheta_inner)+1);&lt;br /&gt;
&lt;br /&gt;
        cells(end+1,:) = [a, b, c];&lt;br /&gt;
        regions(end+1) = 1;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_1 (menos el centro) - anillos interiores,&lt;br /&gt;
    % Omega_1&lt;br /&gt;
    for k = 2:k_if&lt;br /&gt;
        &lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior (de Omega_1)&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior (de Omega_1)&lt;br /&gt;
        N = ntheta_inner; %número de nodos en cada anillo&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); % el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo&lt;br /&gt;
            regions(end+1) = 1; %marcamos este triángulo como uno de Omega_1&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 1;%lo marcamos como de Omega_1&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % triangulación de Omega_2&lt;br /&gt;
    for k = k_if+1:n_rings-1&lt;br /&gt;
        inner = ring_nodes{k}; %anillo interior de Omega_2&lt;br /&gt;
        outer = ring_nodes{k+1}; %anillo exterior de Omega_2&lt;br /&gt;
        N = ntheta_outer; %número de nodos&lt;br /&gt;
&lt;br /&gt;
        for j = 1:N&lt;br /&gt;
            a = inner(j); %un nodo interior&lt;br /&gt;
            b = inner(mod(j,N)+1); %el siguiente nodo interior&lt;br /&gt;
            c = outer(j); %un nodo exterior&lt;br /&gt;
            d = outer(mod(j,N)+1); %el siguiente nodo exterior&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a b d]; %primer triángulo del cuadrilátero&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
&lt;br /&gt;
            cells(end+1,:) = [a d c]; %segundo triángulo&lt;br /&gt;
            regions(end+1) = 2;%lo marcamos como de Omega_2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    % lo guardamos&lt;br /&gt;
    save(save_path, &amp;quot;points&amp;quot;, &amp;quot;cells&amp;quot;, &amp;quot;regions&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Código: generate_mesh.m ==&lt;br /&gt;
&lt;br /&gt;
== Código: plot_mesh.m ==&lt;br /&gt;
&lt;br /&gt;
== Código: plot_solution.m ==&lt;br /&gt;
&lt;br /&gt;
== Código: assemble_system.m ==&lt;br /&gt;
&lt;br /&gt;
== Código: main.m ==&lt;br /&gt;
&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86249</id>
		<title>Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Distribuci%C3%B3n_del_Potencial_El%C3%A9ctrico_Cerebral_(Modelo_2D)_-_CAN&amp;diff=86249"/>
				<updated>2025-11-16T20:10:00Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: Página creada con «{{ TrabajoMNEDP | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | MNEDP|2025-26 | Claudia Domínguez, I...»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoMNEDP | Distribución del Potencial Eléctrico Cerebral (Modelo 2D) - CAN | [[:Categoría:MNEDP|MNEDP]]|[[:Categoría:MNEDP25/26|2025-26]] | Claudia Domínguez, Ignacio Martínez, Analía Olivero}}&lt;br /&gt;
&lt;br /&gt;
=Póster del Trabajo=&lt;br /&gt;
Por ahora no está! (carita triste)&lt;br /&gt;
=Códigos de MatLab=&lt;br /&gt;
Por ahora tampoco está! (carita triste)&lt;br /&gt;
[[Categoría:MNEDP|MNEDP]]&lt;br /&gt;
[[Categoría:MNEDP25/26|2025-26]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_de_Laplace_y_de_Poisson_(ILA)&amp;diff=85141</id>
		<title>Ecuación de Laplace y de Poisson (ILA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_de_Laplace_y_de_Poisson_(ILA)&amp;diff=85141"/>
				<updated>2025-04-20T19:58:58Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación de Laplace y de Poisson (Grupo ILA). | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | &lt;br /&gt;
*Alicia Ruiz, &lt;br /&gt;
*Luis Ramos&lt;br /&gt;
*Ignacio Martínez&lt;br /&gt;
.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_de_Laplace_y_de_Poisson_(ILA)&amp;diff=85140</id>
		<title>Ecuación de Laplace y de Poisson (ILA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_de_Laplace_y_de_Poisson_(ILA)&amp;diff=85140"/>
				<updated>2025-04-20T19:58:36Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación de Laplace y de Poisson (Grupo ILA). | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | &lt;br /&gt;
*Alicia Ruiz, &lt;br /&gt;
*Ignacio Martínez, &lt;br /&gt;
*todos.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=85132</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=85132"/>
				<updated>2025-03-20T07:31:37Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo ILIA | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor sin fuente térmica:''' resolvemos el problema con condiciones iniciales y de frontera, y obtenemos la solución estacionaria.&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
*'''Comparación entre ambas:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
En los casos sencillos de la ecuación del calor, como los vistos en clase, no existe aporte de calor a nuestro sistema o, si existe, es regular a lo largo del espacio y el tiempo. Sin embargo, en muchas situaciones prácticas, el calor puede ser generado en puntos específicos del dominio. Para modelar este efecto, introducimos una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto concreto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra de manera localizada. Así, la ecuación del calor modificada queda como sigue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es una fuente térmica localizada, que modelamos como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aquí, &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac, que hace que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Para ilustrar este fenómeno, consideramos el mismo problema de la sección 2 pero con la fuente térmica puntual en &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt;, con una intensidad constante &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;. Obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si intentamos resolver este problema suponiendo la existencia de una solución estacionaria, debemos realizar la suposición de que la integral de la función &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; es la función Heaviside, es decir:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
H(x) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
0 &amp;amp; x &amp;lt;0\\&lt;br /&gt;
1 &amp;amp; x \geq 0&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Con esta información:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    -u_{xx}(x) &amp;amp;= 2\delta(x-0.5)\\&lt;br /&gt;
    \Rightarrow  -u_x(x) &amp;amp;= 2\int \delta(x-0.5)dx = 2H(x-0.5) + 2C_1= \begin{cases}&lt;br /&gt;
        2C_1 &amp;amp;\text{ si } x&amp;lt; 0.5\\&lt;br /&gt;
        2+2C_1 &amp;amp; \text{ si } x \geq 0.5&lt;br /&gt;
    \end{cases}\\&lt;br /&gt;
    \Rightarrow -u(x) &amp;amp;= 2\int H(x-0.5)dx  + 2C_1\cdot x\\&lt;br /&gt;
    \Rightarrow  -u(x) &amp;amp; = 2\cdot\left((x-0.5)H(x-0.5) + C_2 + C_1\cdot x\right)\\&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Evaluando en las condiciones iniciales, llegamos a:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(0) = (-0.5)H(-0.5) + C_2\\&lt;br /&gt;
    0&amp;amp;= 0 + C_2 \\&lt;br /&gt;
\Rightarrow  C_2 &amp;amp;= 0&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(1) = (0.5)H(0.5) + C_1+ C_2\\&lt;br /&gt;
    0&amp;amp;= 0.5 + C_1\\&lt;br /&gt;
    \Rightarrow  C_1 &amp;amp;= -0.5&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Luego nuestra solución tendría la forma:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
    u(x) = 2 \left(-\left(\frac{2x-1}{2}\right)H\left(\frac{2x-1}{2}\right) +\frac{x}{2}\right)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Representando nuestra solución estacionaria, llegamos a:&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Solución estacionaria ILIA 2025 8K.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por la forma de nuestra ecuación cabría esperar una solución que, además de las condiciones iniciales, tenga (y a simple vista se aprecie) una zona de temperatura máxima en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt;, donde a ambos lados la temperatura descendería hasta llegar a los extremos, donde la temperatura es constantemente nula.&lt;br /&gt;
&lt;br /&gt;
Vista la solución estacionaria y vista que coincide con la hallada numéricamente, sin embargo, resulta algo difícil operar con estas funciones para hallar la solución homogeneizada, con lo que habitualmente se emplean formas alternativas de resolver el problema que involucran expresar la &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; como una combinación de las funciones de nuestra base de Fourier.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:EvolucionILIA.jpeg|400px|thumb|right|Evolución temporal de la ecuación del calor con fuente térmica]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
import numba&lt;br /&gt;
&lt;br /&gt;
# Parámetros del problema&lt;br /&gt;
L = 1.0  # Longitud del dominio espacial&lt;br /&gt;
t0 = 0 #Tiempo inicial&lt;br /&gt;
T = 0.1  # Tiempo final&lt;br /&gt;
nx = 100  # Número de puntos en la dirección x&lt;br /&gt;
nt = 10000  # Número de pasos de tiempo&lt;br /&gt;
dx = L / (nx - 1) # diferencia en espacio &lt;br /&gt;
dt = (T-t0) / nt # diferencia en tiempo&lt;br /&gt;
alpha = 1.0  # Coeficiente de difusión (para la ecuación del calor)&lt;br /&gt;
r = alpha * dt / (dx**2) #Coeficiente de estabilidad&lt;br /&gt;
&lt;br /&gt;
# Verificamos que se cumple la cond. de estabilidad para el esquema&lt;br /&gt;
if r &amp;gt; 0.5:&lt;br /&gt;
    raise ValueError(f&amp;quot;La condición de estabilidad no se cumple, 0.5 &amp;lt; {r=}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo discretizado en x&lt;br /&gt;
x = np.linspace(0, L, nx)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo en t que vamos a emplear&lt;br /&gt;
t = np.linspace(t0, T, nt + 1)&lt;br /&gt;
&lt;br /&gt;
#Creamos el mallado en x y t:&lt;br /&gt;
X,T_mesh = np.meshgrid(x,t)&lt;br /&gt;
&lt;br /&gt;
# Inicializar la solución u(x, t) con ceros&lt;br /&gt;
u = np.zeros((nt + 1, nx))&lt;br /&gt;
&lt;br /&gt;
# Aplicamos las condiciones de frontera e inicial&lt;br /&gt;
u[:, 0] = 0&lt;br /&gt;
u[:, -1] = 0&lt;br /&gt;
u[0, :] = np.sin(2*np.pi*x)&lt;br /&gt;
&lt;br /&gt;
# Calculamos el índice del punto más cercano a x = 0.5&lt;br /&gt;
index_source = int(0.5 / dx)&lt;br /&gt;
&lt;br /&gt;
# Evolución temporal&lt;br /&gt;
for n in range(nt):&lt;br /&gt;
    u[n + 1, :] = u[n, :]  # Inicializar la siguiente iteración con los valores actuales&lt;br /&gt;
    for i in range(1, nx - 1):&lt;br /&gt;
        u[n + 1, i] = u[n, i] + r * (u[n, i + 1] - 2 * u[n, i] + u[n, i - 1])&lt;br /&gt;
    # Aproximación de la delta de Dirac&lt;br /&gt;
    u[n + 1, index_source] += 2 * dt / dx&lt;br /&gt;
&lt;br /&gt;
# Crear la figura y el subplot 3D&lt;br /&gt;
fig = plt.figure(figsize=(12, 8))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# Graficar la superficie, y añadimos etiquetas, barra de color, etc.&lt;br /&gt;
surf = ax.plot_surface(X, T_mesh, u, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('x')&lt;br /&gt;
ax.set_ylabel('t')&lt;br /&gt;
ax.set_zlabel('u(x, t)')&lt;br /&gt;
ax.set_title('Evolución temporal de la ecuación de calor con fuente (aproximación numérica)')&lt;br /&gt;
fig.colorbar(surf, ax=ax, label='u(x, t)')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Interpretación de la solución numérica y comparación con el caso sin fuente===&lt;br /&gt;
Los resultados numéricos muestran que efectivamente la fuente térmica localizada en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; genera una acumulación de calor en su entorno inmediato. A medida que avanza el tiempo, se observa la disipación progresiva del calor debido a la difusión, que suaviza la temperatura alrededor de este punto, extendiéndola hacia el resto del dominio.&lt;br /&gt;
&lt;br /&gt;
En comparación con el caso sin fuente, donde la temperatura inicial se disipa homogéneamente y tiende a cero en todo el dominio, en este caso se observa un comportamiento diferente: la región en torno a &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; se mantiene significativamente más caliente durante más tiempo. Esto refleja el efecto de la fuente térmica puntual, que introduce energía de manera continua en el sistema, impidiendo que la temperatura disminuya de forma uniforme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=85131</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=85131"/>
				<updated>2025-03-20T07:31:09Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo ILIA | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor sin fuente térmica:''' resolvemos el problema con condiciones iniciales y de frontera, y obtenemos la solución estacionaria.&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
*'''Comparación entre ambas:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
En los casos sencillos de la ecuación del calor, como los vistos en clase, no existe aporte de calor a nuestro sistema o, si existe, es regular a lo largo del espacio y el tiempo. Sin embargo, en muchas situaciones prácticas, el calor puede ser generado en puntos específicos del dominio. Para modelar este efecto, introducimos una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto concreto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra de manera localizada. Así, la ecuación del calor modificada queda como sigue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es una fuente térmica localizada, que modelamos como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aquí, &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac, que hace que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Para ilustrar este fenómeno, consideramos el mismo problema de la sección 2 pero con la fuente térmica puntual en &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt;, con una intensidad constante &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;. Obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si intentamos resolver este problema suponiendo la existencia de una solución estacionaria, debemos realizar la suposición de que la integral de la función &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; es la función Heaviside, es decir:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
H(x) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
0 &amp;amp; x &amp;lt;0\\&lt;br /&gt;
1 &amp;amp; x \geq 0&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Con esta información:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    -u_{xx}(x) &amp;amp;= 2\delta(x-0.5)\\&lt;br /&gt;
    \Rightarrow  -u_x(x) &amp;amp;= 2\int \delta(x-0.5)dx = 2H(x-0.5) + 2C_1= \begin{cases}&lt;br /&gt;
        2C_1 &amp;amp;\text{ si } x&amp;lt; 0.5\\&lt;br /&gt;
        2+2C_1 &amp;amp; \text{ si } x \geq 0.5&lt;br /&gt;
    \end{cases}\\&lt;br /&gt;
    \Rightarrow -u(x) &amp;amp;= 2\int H(x-0.5)dx  + 2C_1\cdot x\\&lt;br /&gt;
    \Rightarrow  -u(x) &amp;amp; = 2\cdot\left((x-0.5)H(x-0.5) + C_2 + C_1\cdot x\right)\\&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Evaluando en las condiciones iniciales, llegamos a:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(0) = (-0.5)H(-0.5) + C_2\\&lt;br /&gt;
    0&amp;amp;= 0 + C_2 \\&lt;br /&gt;
\Rightarrow  C_2 &amp;amp;= 0&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(1) = (0.5)H(0.5) + C_1+ C_2\\&lt;br /&gt;
    0&amp;amp;= 0.5 + C_1\\&lt;br /&gt;
    \Rightarrow  C_1 &amp;amp;= -0.5&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Luego nuestra solución tendría la forma:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
    u(x) = 2 \left(-\frac{2x-1}{2}H\left(\frac{2x-1}{2}\right) +\frac{x}{2}\right)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Representando nuestra solución estacionaria, llegamos a:&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Solución estacionaria ILIA 2025 8K.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por la forma de nuestra ecuación cabría esperar una solución que, además de las condiciones iniciales, tenga (y a simple vista se aprecie) una zona de temperatura máxima en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt;, donde a ambos lados la temperatura descendería hasta llegar a los extremos, donde la temperatura es constantemente nula.&lt;br /&gt;
&lt;br /&gt;
Vista la solución estacionaria y vista que coincide con la hallada numéricamente, sin embargo, resulta algo difícil operar con estas funciones para hallar la solución homogeneizada, con lo que habitualmente se emplean formas alternativas de resolver el problema que involucran expresar la &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; como una combinación de las funciones de nuestra base de Fourier.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:EvolucionILIA.jpeg|400px|thumb|right|Evolución temporal de la ecuación del calor con fuente térmica]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
import numba&lt;br /&gt;
&lt;br /&gt;
# Parámetros del problema&lt;br /&gt;
L = 1.0  # Longitud del dominio espacial&lt;br /&gt;
t0 = 0 #Tiempo inicial&lt;br /&gt;
T = 0.1  # Tiempo final&lt;br /&gt;
nx = 100  # Número de puntos en la dirección x&lt;br /&gt;
nt = 10000  # Número de pasos de tiempo&lt;br /&gt;
dx = L / (nx - 1) # diferencia en espacio &lt;br /&gt;
dt = (T-t0) / nt # diferencia en tiempo&lt;br /&gt;
alpha = 1.0  # Coeficiente de difusión (para la ecuación del calor)&lt;br /&gt;
r = alpha * dt / (dx**2) #Coeficiente de estabilidad&lt;br /&gt;
&lt;br /&gt;
# Verificamos que se cumple la cond. de estabilidad para el esquema&lt;br /&gt;
if r &amp;gt; 0.5:&lt;br /&gt;
    raise ValueError(f&amp;quot;La condición de estabilidad no se cumple, 0.5 &amp;lt; {r=}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo discretizado en x&lt;br /&gt;
x = np.linspace(0, L, nx)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo en t que vamos a emplear&lt;br /&gt;
t = np.linspace(t0, T, nt + 1)&lt;br /&gt;
&lt;br /&gt;
#Creamos el mallado en x y t:&lt;br /&gt;
X,T_mesh = np.meshgrid(x,t)&lt;br /&gt;
&lt;br /&gt;
# Inicializar la solución u(x, t) con ceros&lt;br /&gt;
u = np.zeros((nt + 1, nx))&lt;br /&gt;
&lt;br /&gt;
# Aplicamos las condiciones de frontera e inicial&lt;br /&gt;
u[:, 0] = 0&lt;br /&gt;
u[:, -1] = 0&lt;br /&gt;
u[0, :] = np.sin(2*np.pi*x)&lt;br /&gt;
&lt;br /&gt;
# Calculamos el índice del punto más cercano a x = 0.5&lt;br /&gt;
index_source = int(0.5 / dx)&lt;br /&gt;
&lt;br /&gt;
# Evolución temporal&lt;br /&gt;
for n in range(nt):&lt;br /&gt;
    u[n + 1, :] = u[n, :]  # Inicializar la siguiente iteración con los valores actuales&lt;br /&gt;
    for i in range(1, nx - 1):&lt;br /&gt;
        u[n + 1, i] = u[n, i] + r * (u[n, i + 1] - 2 * u[n, i] + u[n, i - 1])&lt;br /&gt;
    # Aproximación de la delta de Dirac&lt;br /&gt;
    u[n + 1, index_source] += 2 * dt / dx&lt;br /&gt;
&lt;br /&gt;
# Crear la figura y el subplot 3D&lt;br /&gt;
fig = plt.figure(figsize=(12, 8))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# Graficar la superficie, y añadimos etiquetas, barra de color, etc.&lt;br /&gt;
surf = ax.plot_surface(X, T_mesh, u, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('x')&lt;br /&gt;
ax.set_ylabel('t')&lt;br /&gt;
ax.set_zlabel('u(x, t)')&lt;br /&gt;
ax.set_title('Evolución temporal de la ecuación de calor con fuente (aproximación numérica)')&lt;br /&gt;
fig.colorbar(surf, ax=ax, label='u(x, t)')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Interpretación de la solución numérica y comparación con el caso sin fuente===&lt;br /&gt;
Los resultados numéricos muestran que efectivamente la fuente térmica localizada en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; genera una acumulación de calor en su entorno inmediato. A medida que avanza el tiempo, se observa la disipación progresiva del calor debido a la difusión, que suaviza la temperatura alrededor de este punto, extendiéndola hacia el resto del dominio.&lt;br /&gt;
&lt;br /&gt;
En comparación con el caso sin fuente, donde la temperatura inicial se disipa homogéneamente y tiende a cero en todo el dominio, en este caso se observa un comportamiento diferente: la región en torno a &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; se mantiene significativamente más caliente durante más tiempo. Esto refleja el efecto de la fuente térmica puntual, que introduce energía de manera continua en el sistema, impidiendo que la temperatura disminuya de forma uniforme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=85130</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=85130"/>
				<updated>2025-03-20T07:29:33Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo ILIA | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor sin fuente térmica:''' resolvemos el problema con condiciones iniciales y de frontera, y obtenemos la solución estacionaria.&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
*'''Comparación entre ambas:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
En los casos sencillos de la ecuación del calor, como los vistos en clase, no existe aporte de calor a nuestro sistema o, si existe, es regular a lo largo del espacio y el tiempo. Sin embargo, en muchas situaciones prácticas, el calor puede ser generado en puntos específicos del dominio. Para modelar este efecto, introducimos una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto concreto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra de manera localizada. Así, la ecuación del calor modificada queda como sigue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es una fuente térmica localizada, que modelamos como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aquí, &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac, que hace que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Para ilustrar este fenómeno, consideramos el mismo problema de la sección 2 pero con la fuente térmica puntual en &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt;, con una intensidad constante &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;. Obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si intentamos resolver este problema suponiendo la existencia de una solución estacionaria, debemos realizar la suposición de que la integral de la función &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; es la función Heaviside, es decir:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
H(x) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
0 &amp;amp; x &amp;lt;0\\&lt;br /&gt;
1 &amp;amp; x \geq 0&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Con esta información:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    -u_{xx}(x) &amp;amp;= 2\delta(x-0.5)\\&lt;br /&gt;
    \Rightarrow  -u_x(x) &amp;amp;= 2\int \delta(x-0.5)dx = 2H(x-0.5) + 2C_1= \begin{cases}&lt;br /&gt;
        2C_1 &amp;amp;\text{ si } x&amp;lt; 0.5\\&lt;br /&gt;
        2+2C_1 &amp;amp; \text{ si } x \geq 0.5&lt;br /&gt;
    \end{cases}\\&lt;br /&gt;
    \Rightarrow -u(x) &amp;amp;= 2\int H(x-0.5)dx  + 2C_1\cdot x\\&lt;br /&gt;
    \Rightarrow  -u(x) &amp;amp; = 2\cdot\left((x-0.5)H(x-0.5) + C_2 + C_1\cdot x\right)\\&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Evaluando en las condiciones iniciales, llegamos a:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(0) = (-0.5)H(-0.5) + C_2\\&lt;br /&gt;
    0&amp;amp;= 0 + C_2 \\&lt;br /&gt;
\Rightarrow  C_2 &amp;amp;= 0&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(1) = (0.5)H(0.5) + C_1+ C_2\\&lt;br /&gt;
    0&amp;amp;= 0.5 + C_1\\&lt;br /&gt;
    \Rightarrow  C_1 &amp;amp;= -0.5&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Luego nuestra solución tendría la forma:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
    u(x) = 2 \left(-\frac{2x-1}{2}H\left(\frac{2x-1}{2}\right +\frac{x}{2}\right)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Representando nuestra solución estacionaria, llegamos a:&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Solución estacionaria ILIA 2025 8K.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por la forma de nuestra ecuación cabría esperar una solución que, además de las condiciones iniciales, tenga (y a simple vista se aprecie) una zona de temperatura máxima en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt;, donde a ambos lados la temperatura descendería hasta llegar a los extremos, donde la temperatura es constantemente nula.&lt;br /&gt;
&lt;br /&gt;
Vista la solución estacionaria y vista que coincide con la hallada numéricamente, sin embargo, resulta algo difícil operar con estas funciones para hallar la solución homogeneizada, con lo que habitualmente se emplean formas alternativas de resolver el problema que involucran expresar la &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; como una combinación de las funciones de nuestra base de Fourier.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:EvolucionILIA.jpeg|400px|thumb|right|Evolución temporal de la ecuación del calor con fuente térmica]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
import numba&lt;br /&gt;
&lt;br /&gt;
# Parámetros del problema&lt;br /&gt;
L = 1.0  # Longitud del dominio espacial&lt;br /&gt;
t0 = 0 #Tiempo inicial&lt;br /&gt;
T = 0.1  # Tiempo final&lt;br /&gt;
nx = 100  # Número de puntos en la dirección x&lt;br /&gt;
nt = 10000  # Número de pasos de tiempo&lt;br /&gt;
dx = L / (nx - 1) # diferencia en espacio &lt;br /&gt;
dt = (T-t0) / nt # diferencia en tiempo&lt;br /&gt;
alpha = 1.0  # Coeficiente de difusión (para la ecuación del calor)&lt;br /&gt;
r = alpha * dt / (dx**2) #Coeficiente de estabilidad&lt;br /&gt;
&lt;br /&gt;
# Verificamos que se cumple la cond. de estabilidad para el esquema&lt;br /&gt;
if r &amp;gt; 0.5:&lt;br /&gt;
    raise ValueError(f&amp;quot;La condición de estabilidad no se cumple, 0.5 &amp;lt; {r=}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo discretizado en x&lt;br /&gt;
x = np.linspace(0, L, nx)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo en t que vamos a emplear&lt;br /&gt;
t = np.linspace(t0, T, nt + 1)&lt;br /&gt;
&lt;br /&gt;
#Creamos el mallado en x y t:&lt;br /&gt;
X,T_mesh = np.meshgrid(x,t)&lt;br /&gt;
&lt;br /&gt;
# Inicializar la solución u(x, t) con ceros&lt;br /&gt;
u = np.zeros((nt + 1, nx))&lt;br /&gt;
&lt;br /&gt;
# Aplicamos las condiciones de frontera e inicial&lt;br /&gt;
u[:, 0] = 0&lt;br /&gt;
u[:, -1] = 0&lt;br /&gt;
u[0, :] = np.sin(2*np.pi*x)&lt;br /&gt;
&lt;br /&gt;
# Calculamos el índice del punto más cercano a x = 0.5&lt;br /&gt;
index_source = int(0.5 / dx)&lt;br /&gt;
&lt;br /&gt;
# Evolución temporal&lt;br /&gt;
for n in range(nt):&lt;br /&gt;
    u[n + 1, :] = u[n, :]  # Inicializar la siguiente iteración con los valores actuales&lt;br /&gt;
    for i in range(1, nx - 1):&lt;br /&gt;
        u[n + 1, i] = u[n, i] + r * (u[n, i + 1] - 2 * u[n, i] + u[n, i - 1])&lt;br /&gt;
    # Aproximación de la delta de Dirac&lt;br /&gt;
    u[n + 1, index_source] += 2 * dt / dx&lt;br /&gt;
&lt;br /&gt;
# Crear la figura y el subplot 3D&lt;br /&gt;
fig = plt.figure(figsize=(12, 8))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# Graficar la superficie, y añadimos etiquetas, barra de color, etc.&lt;br /&gt;
surf = ax.plot_surface(X, T_mesh, u, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('x')&lt;br /&gt;
ax.set_ylabel('t')&lt;br /&gt;
ax.set_zlabel('u(x, t)')&lt;br /&gt;
ax.set_title('Evolución temporal de la ecuación de calor con fuente (aproximación numérica)')&lt;br /&gt;
fig.colorbar(surf, ax=ax, label='u(x, t)')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Interpretación de la solución numérica y comparación con el caso sin fuente===&lt;br /&gt;
Los resultados numéricos muestran que efectivamente la fuente térmica localizada en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; genera una acumulación de calor en su entorno inmediato. A medida que avanza el tiempo, se observa la disipación progresiva del calor debido a la difusión, que suaviza la temperatura alrededor de este punto, extendiéndola hacia el resto del dominio.&lt;br /&gt;
&lt;br /&gt;
En comparación con el caso sin fuente, donde la temperatura inicial se disipa homogéneamente y tiende a cero en todo el dominio, en este caso se observa un comportamiento diferente: la región en torno a &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; se mantiene significativamente más caliente durante más tiempo. Esto refleja el efecto de la fuente térmica puntual, que introduce energía de manera continua en el sistema, impidiendo que la temperatura disminuya de forma uniforme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84987</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84987"/>
				<updated>2025-03-19T11:17:41Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo ILIA | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor sin fuente térmica:''' resolvemos el problema con condiciones iniciales y de frontera, y obtenemos la solución estacionaria.&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
*'''Comparación entre ambas:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
En los casos sencillos de la ecuación del calor, como los vistos en clase, no existe aporte de calor a nuestro sistema o, si existe, es regular a lo largo del espacio y el tiempo. Sin embargo, en muchas situaciones prácticas, el calor puede ser generado en puntos específicos del dominio. Para modelar este efecto, introducimos una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto concreto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra de manera localizada. Así, la ecuación del calor modificada queda como sigue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es una fuente térmica localizada, que modelamos como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aquí, &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac, que hace que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Para ilustrar este fenómeno, consideramos el mismo problema de la sección 2 pero con la fuente térmica puntual en &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt;, con una intensidad constante &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;. Obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si intentamos resolver este problema suponiendo la existencia de una solución estacionaria, debemos realizar la suposición de que la integral de la función &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; es la función Heaviside, es decir:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
H(x) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
0 &amp;amp; x &amp;lt;0\\&lt;br /&gt;
1 &amp;amp; x \geq 0&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Con esta información:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    -u_{xx}(x) &amp;amp;= 2\delta(x-0.5)\\&lt;br /&gt;
    \Rightarrow  -u_x(x) &amp;amp;= 2\int \delta(x-0.5)dx = 2H(x-0.5) + 2C_1= \begin{cases}&lt;br /&gt;
        2C_1 &amp;amp;\text{ si } x&amp;lt; 0.5\\&lt;br /&gt;
        2+2C_1 &amp;amp; \text{ si } x \geq 0.5&lt;br /&gt;
    \end{cases}\\&lt;br /&gt;
    \Rightarrow -u(x) &amp;amp;= 2\int H(x-0.5)dx  + 2C_1\cdot x\\&lt;br /&gt;
    \Rightarrow  -u(x) &amp;amp; = 2\cdot\left((x-0.5)H(x-0.5) + C_2 + C_1\cdot x\right)\\&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Evaluando en las condiciones iniciales, llegamos a:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(0) = (-0.5)H(-0.5) + C_2\\&lt;br /&gt;
    0&amp;amp;= 0 + C_2 \\&lt;br /&gt;
\Rightarrow  C_2 &amp;amp;= 0&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(1) = (0.5)H(0.5) + C_1+ C_2\\&lt;br /&gt;
    0&amp;amp;= 0.5 + C_2\\&lt;br /&gt;
    \Rightarrow  C_2 &amp;amp;= -0.5&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Luego nuestra solución tendría la forma:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
    u(x) = 2\cdot\left(\left(\frac{2x-1}{2}\right)H\left(\frac{2x-1}{2}\right) +  \frac{x}{2}\right)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Representando nuestra solución estacionaria, llegamos a:&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Solución estacionaria ILIA 2025 8K.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por la forma de nuestra ecuación cabría esperar una solución que, además de las condiciones iniciales, tenga (y a simple vista se aprecie) una zona de temperatura máxima en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt;, donde a ambos lados la temperatura descendería hasta llegar a los extremos, donde la temperatura es constantemente nula.&lt;br /&gt;
&lt;br /&gt;
Vista la solución estacionaria y vista que coincide con la hallada numéricamente, sin embargo, resulta algo difícil operar con estas funciones para hallar la solución homogeneizada, con lo que habitualmente se emplean formas alternativas de resolver el problema que involucran expresar la &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; como una combinación de las funciones de nuestra base de Fourier.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:EvolucionILIA.jpeg|400px|thumb|right|Evolución temporal de la ecuación del calor con fuente térmica]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
import numba&lt;br /&gt;
&lt;br /&gt;
# Parámetros del problema&lt;br /&gt;
L = 1.0  # Longitud del dominio espacial&lt;br /&gt;
t0 = 0 #Tiempo inicial&lt;br /&gt;
T = 0.1  # Tiempo final&lt;br /&gt;
nx = 100  # Número de puntos en la dirección x&lt;br /&gt;
nt = 10000  # Número de pasos de tiempo&lt;br /&gt;
dx = L / (nx - 1) # diferencia en espacio &lt;br /&gt;
dt = (T-t0) / nt # diferencia en tiempo&lt;br /&gt;
alpha = 1.0  # Coeficiente de difusión (para la ecuación del calor)&lt;br /&gt;
r = alpha * dt / (dx**2) #Coeficiente de estabilidad&lt;br /&gt;
&lt;br /&gt;
# Verificamos que se cumple la cond. de estabilidad para el esquema&lt;br /&gt;
if r &amp;gt; 0.5:&lt;br /&gt;
    raise ValueError(f&amp;quot;La condición de estabilidad no se cumple, 0.5 &amp;lt; {r=}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo discretizado en x&lt;br /&gt;
x = np.linspace(0, L, nx)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo en t que vamos a emplear&lt;br /&gt;
t = np.linspace(t0, T, nt + 1)&lt;br /&gt;
&lt;br /&gt;
#Creamos el mallado en x y t:&lt;br /&gt;
X,T_mesh = np.meshgrid(x,t)&lt;br /&gt;
&lt;br /&gt;
# Inicializar la solución u(x, t) con ceros&lt;br /&gt;
u = np.zeros((nt + 1, nx))&lt;br /&gt;
&lt;br /&gt;
# Aplicamos las condiciones de frontera e inicial&lt;br /&gt;
u[:, 0] = 0&lt;br /&gt;
u[:, -1] = 0&lt;br /&gt;
u[0, :] = np.sin(2*np.pi*x)&lt;br /&gt;
&lt;br /&gt;
# Calculamos el índice del punto más cercano a x = 0.5&lt;br /&gt;
index_source = int(0.5 / dx)&lt;br /&gt;
&lt;br /&gt;
# Evolución temporal&lt;br /&gt;
for n in range(nt):&lt;br /&gt;
    u[n + 1, :] = u[n, :]  # Inicializar la siguiente iteración con los valores actuales&lt;br /&gt;
    for i in range(1, nx - 1):&lt;br /&gt;
        u[n + 1, i] = u[n, i] + r * (u[n, i + 1] - 2 * u[n, i] + u[n, i - 1])&lt;br /&gt;
    # Aproximación de la delta de Dirac&lt;br /&gt;
    u[n + 1, index_source] += 2 * dt / dx&lt;br /&gt;
&lt;br /&gt;
# Crear la figura y el subplot 3D&lt;br /&gt;
fig = plt.figure(figsize=(12, 8))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# Graficar la superficie, y añadimos etiquetas, barra de color, etc.&lt;br /&gt;
surf = ax.plot_surface(X, T_mesh, u, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('x')&lt;br /&gt;
ax.set_ylabel('t')&lt;br /&gt;
ax.set_zlabel('u(x, t)')&lt;br /&gt;
ax.set_title('Evolución temporal de la ecuación de calor con fuente (aproximación numérica)')&lt;br /&gt;
fig.colorbar(surf, ax=ax, label='u(x, t)')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Interpretación de la solución numérica y comparación con el caso sin fuente===&lt;br /&gt;
Los resultados numéricos muestran que efectivamente la fuente térmica localizada en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; genera una acumulación de calor en su entorno inmediato. A medida que avanza el tiempo, se observa la disipación progresiva del calor debido a la difusión, que suaviza la temperatura alrededor de este punto, extendiéndola hacia el resto del dominio.&lt;br /&gt;
&lt;br /&gt;
En comparación con el caso sin fuente, donde la temperatura inicial se disipa homogéneamente y tiende a cero en todo el dominio, en este caso se observa un comportamiento diferente: la región en torno a &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; se mantiene significativamente más caliente durante más tiempo. Esto refleja el efecto de la fuente térmica puntual, que introduce energía de manera continua en el sistema, impidiendo que la temperatura disminuya de forma uniforme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84986</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84986"/>
				<updated>2025-03-19T11:14:51Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo ILIA | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor sin fuente térmica:''' resolvemos el problema con condiciones iniciales y de frontera, y obtenemos la solución estacionaria.&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
*'''Comparación entre ambas:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
En los casos sencillos de la ecuación del calor, como los vistos en clase, no existe aporte de calor a nuestro sistema o, si existe, es regular a lo largo del espacio y el tiempo. Sin embargo, en muchas situaciones prácticas, el calor puede ser generado en puntos específicos del dominio. Para modelar este efecto, introducimos una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto concreto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra de manera localizada. Así, la ecuación del calor modificada queda como sigue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es una fuente térmica localizada, que modelamos como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aquí, &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac, que hace que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Para ilustrar este fenómeno, consideramos el mismo problema de la sección 2 pero con la fuente térmica puntual en &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt;, con una intensidad constante &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;. Obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si intentamos resolver este problema suponiendo la existencia de una solución estacionaria, debemos realizar la suposición de que la integral de la función &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; es la función Heaviside, es decir:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
H(x) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
0 &amp;amp; x &amp;lt;0\\&lt;br /&gt;
1 &amp;amp; x \geq 0&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Con esta información:&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    -u_{xx}(x) &amp;amp;= 2\delta(x-0.5)\\&lt;br /&gt;
    \Rightarrow  -u_x(x) &amp;amp;= 2\int \delta(x-0.5)dx = 2H(x-0.5) + 2C_1= \begin{cases}&lt;br /&gt;
        2C_1 &amp;amp;\text{ si } x&amp;lt; 0.5\\&lt;br /&gt;
        2+2C_1 &amp;amp; \text{ si } x \geq 0.5&lt;br /&gt;
    \end{cases}\\&lt;br /&gt;
    \Rightarrow -u(x) &amp;amp;= 2\int H(x-0.5)dx  + 2C_1\cdot x\\&lt;br /&gt;
    \Rightarrow  -u(x) &amp;amp; = 2\cdot\left((x-0.5)H(x-0.5) + C_2 + C_1\cdot x\right)\\&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Evaluando en las condiciones iniciales, llegamos a:&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(0) = (-0.5)H(-0.5) + C_2\\&lt;br /&gt;
    0&amp;amp;= 0 + C_2 \Rightarrow  C_2 = 0&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(1) = (0.5)H(0.5) + C_1+ C_2\\&lt;br /&gt;
    0&amp;amp;= 0.5 + C_2\\&lt;br /&gt;
    \Rightarrow  C_2 &amp;amp;= -0.5&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Luego nuestra solución tendría la forma:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
    u(x) = 2\cdot\left(\left(\frac{2x-1}{2}\right)H\left(\frac{2x-1}{2}\right) +  \frac{x}{2}\right)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Representando nuestra solución estacionaria, llegamos a:&lt;br /&gt;
&lt;br /&gt;
[[Archivo:Solución estacionaria ILIA 2025 8K.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Por la forma de nuestra ecuación cabría esperar una solución que, además de las condiciones iniciales, tenga (y a simple vista se aprecie) una zona de temperatura máxima en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt;, donde a ambos lados la temperatura descendería hasta llegar a los extremos, donde la temperatura es constantemente nula.&lt;br /&gt;
&lt;br /&gt;
Vista la solución estacionaria y vista que coincide con la hallada numéricamente, sin embargo, resulta algo difícil operar con estas funciones para hallar la solución homogeneizada, con lo que habitualmente se emplean formas alternativas de resolver el problema que involucran expresar la &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; como una combinación de las funciones de nuestra base de Fourier.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:EvolucionILIA.jpeg|400px|thumb|right|Evolución temporal de la ecuación del calor con fuente térmica]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
import numba&lt;br /&gt;
&lt;br /&gt;
# Parámetros del problema&lt;br /&gt;
L = 1.0  # Longitud del dominio espacial&lt;br /&gt;
t0 = 0 #Tiempo inicial&lt;br /&gt;
T = 0.1  # Tiempo final&lt;br /&gt;
nx = 100  # Número de puntos en la dirección x&lt;br /&gt;
nt = 10000  # Número de pasos de tiempo&lt;br /&gt;
dx = L / (nx - 1) # diferencia en espacio &lt;br /&gt;
dt = (T-t0) / nt # diferencia en tiempo&lt;br /&gt;
alpha = 1.0  # Coeficiente de difusión (para la ecuación del calor)&lt;br /&gt;
r = alpha * dt / (dx**2) #Coeficiente de estabilidad&lt;br /&gt;
&lt;br /&gt;
# Verificamos que se cumple la cond. de estabilidad para el esquema&lt;br /&gt;
if r &amp;gt; 0.5:&lt;br /&gt;
    raise ValueError(f&amp;quot;La condición de estabilidad no se cumple, 0.5 &amp;lt; {r=}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo discretizado en x&lt;br /&gt;
x = np.linspace(0, L, nx)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo en t que vamos a emplear&lt;br /&gt;
t = np.linspace(t0, T, nt + 1)&lt;br /&gt;
&lt;br /&gt;
#Creamos el mallado en x y t:&lt;br /&gt;
X,T_mesh = np.meshgrid(x,t)&lt;br /&gt;
&lt;br /&gt;
# Inicializar la solución u(x, t) con ceros&lt;br /&gt;
u = np.zeros((nt + 1, nx))&lt;br /&gt;
&lt;br /&gt;
# Aplicamos las condiciones de frontera e inicial&lt;br /&gt;
u[:, 0] = 0&lt;br /&gt;
u[:, -1] = 0&lt;br /&gt;
u[0, :] = np.sin(2*np.pi*x)&lt;br /&gt;
&lt;br /&gt;
# Calculamos el índice del punto más cercano a x = 0.5&lt;br /&gt;
index_source = int(0.5 / dx)&lt;br /&gt;
&lt;br /&gt;
# Evolución temporal&lt;br /&gt;
for n in range(nt):&lt;br /&gt;
    u[n + 1, :] = u[n, :]  # Inicializar la siguiente iteración con los valores actuales&lt;br /&gt;
    for i in range(1, nx - 1):&lt;br /&gt;
        u[n + 1, i] = u[n, i] + r * (u[n, i + 1] - 2 * u[n, i] + u[n, i - 1])&lt;br /&gt;
    # Aproximación de la delta de Dirac&lt;br /&gt;
    u[n + 1, index_source] += 2 * dt / dx&lt;br /&gt;
&lt;br /&gt;
# Crear la figura y el subplot 3D&lt;br /&gt;
fig = plt.figure(figsize=(12, 8))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# Graficar la superficie, y añadimos etiquetas, barra de color, etc.&lt;br /&gt;
surf = ax.plot_surface(X, T_mesh, u, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('x')&lt;br /&gt;
ax.set_ylabel('t')&lt;br /&gt;
ax.set_zlabel('u(x, t)')&lt;br /&gt;
ax.set_title('Evolución temporal de la ecuación de calor con fuente (aproximación numérica)')&lt;br /&gt;
fig.colorbar(surf, ax=ax, label='u(x, t)')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Interpretación de la solución numérica y comparación con el caso sin fuente===&lt;br /&gt;
Los resultados numéricos muestran que efectivamente la fuente térmica localizada en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; genera una acumulación de calor en su entorno inmediato. A medida que avanza el tiempo, se observa la disipación progresiva del calor debido a la difusión, que suaviza la temperatura alrededor de este punto, extendiéndola hacia el resto del dominio.&lt;br /&gt;
&lt;br /&gt;
En comparación con el caso sin fuente, donde la temperatura inicial se disipa homogéneamente y tiende a cero en todo el dominio, en este caso se observa un comportamiento diferente: la región en torno a &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; se mantiene significativamente más caliente durante más tiempo. Esto refleja el efecto de la fuente térmica puntual, que introduce energía de manera continua en el sistema, impidiendo que la temperatura disminuya de forma uniforme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Archivo:Soluci%C3%B3n_estacionaria_ILIA_2025_8K.png&amp;diff=84985</id>
		<title>Archivo:Solución estacionaria ILIA 2025 8K.png</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Archivo:Soluci%C3%B3n_estacionaria_ILIA_2025_8K.png&amp;diff=84985"/>
				<updated>2025-03-19T11:13:32Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: Solución estacionaria ILIA Mates 2025, ecuación del calor.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Solución estacionaria ILIA Mates 2025, ecuación del calor.&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84984</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84984"/>
				<updated>2025-03-19T11:08:52Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo ILIA | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor sin fuente térmica:''' resolvemos el problema con condiciones iniciales y de frontera, y obtenemos la solución estacionaria.&lt;br /&gt;
&lt;br /&gt;
*'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
*'''Comparación entre ambas:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
En los casos sencillos de la ecuación del calor, como los vistos en clase, no existe aporte de calor a nuestro sistema o, si existe, es regular a lo largo del espacio y el tiempo. Sin embargo, en muchas situaciones prácticas, el calor puede ser generado en puntos específicos del dominio. Para modelar este efecto, introducimos una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto concreto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra de manera localizada. Así, la ecuación del calor modificada queda como sigue:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es una fuente térmica localizada, que modelamos como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aquí, &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac, que hace que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Para ilustrar este fenómeno, consideramos el mismo problema de la sección 2 pero con la fuente térmica puntual en &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt;, con una intensidad constante &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;. Obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Si intentamos resolver este problema suponiendo la existencia de una solución estacionaria, debemos realizar la suposición de que la integral de la función &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; es la función Heaviside, es decir:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
H(x) = &lt;br /&gt;
\begin{cases}&lt;br /&gt;
0 &amp;amp; x &amp;lt;0\\&lt;br /&gt;
1 &amp;amp; x \geq 0&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Con esta información:&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    -u_{xx}(x) &amp;amp;= 2\delta(x-0.5)\\&lt;br /&gt;
    \Rightarrow  -u_x(x) &amp;amp;= 2\int \delta(x-0.5)dx = 2H(x-0.5) + 2C_1= \begin{cases}&lt;br /&gt;
        2C_1 &amp;amp;\text{ si } x&amp;lt; 0.5\\&lt;br /&gt;
        2+2C_1 &amp;amp; \text{ si } x \geq 0.5&lt;br /&gt;
    \end{cases}\\&lt;br /&gt;
    \Rightarrow -u(x) &amp;amp;= 2\int H(x-0.5)dx  + 2C_1\cdot x\\&lt;br /&gt;
    \Rightarrow  -u(x) &amp;amp; = 2\cdot\left((x-0.5)H(x-0.5) + C_2 + C_1\cdot x\right)\\&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Evaluando en las condiciones iniciales, llegamos a:&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(0) = (-0.5)H(-0.5) + C_2\\&lt;br /&gt;
    0&amp;amp;= 0 + C_2 \Rightarrow  C_2 = 0&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align*}&lt;br /&gt;
    0 &amp;amp;= -u(1) = (0.5)H(0.5) + C_1+ C_2\\&lt;br /&gt;
    0&amp;amp;= 0.5 + C_2\\&lt;br /&gt;
    \Rightarrow  C_2 &amp;amp;= -0.5&lt;br /&gt;
\end{align*}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Luego nuestra solución tendría la forma:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
    u(x) = 2\cdot\left(\left(\frac{2x-1}{2}\right)H\left(\frac{2x-1}{2}\right) +  \frac{x}{2}\right)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
Representando nuestra solución estacionaria, llegamos a:&lt;br /&gt;
&lt;br /&gt;
(imagen)&lt;br /&gt;
&lt;br /&gt;
Por la forma de nuestra ecuación cabría esperar una solución que, además de las condiciones iniciales, tenga (y a simple vista se aprecie) una zona de temperatura máxima en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt;, donde a ambos lados la temperatura descendería hasta llegar a los extremos, donde la temperatura es constantemente nula.&lt;br /&gt;
&lt;br /&gt;
Vista la solución estacionaria y vista que coincide con la hallada numéricamente, sin embargo, resulta algo difícil operar con estas funciones para hallar la solución homogeneizada, con lo que habitualmente se emplean formas alternativas de resolver el problema que involucran expresar la &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; como una combinación de las funciones de nuestra base de Fourier.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:EvolucionILIA.jpeg|400px|thumb|right|Evolución temporal de la ecuación del calor con fuente térmica]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
import numba&lt;br /&gt;
&lt;br /&gt;
# Parámetros del problema&lt;br /&gt;
L = 1.0  # Longitud del dominio espacial&lt;br /&gt;
t0 = 0 #Tiempo inicial&lt;br /&gt;
T = 0.1  # Tiempo final&lt;br /&gt;
nx = 100  # Número de puntos en la dirección x&lt;br /&gt;
nt = 10000  # Número de pasos de tiempo&lt;br /&gt;
dx = L / (nx - 1) # diferencia en espacio &lt;br /&gt;
dt = (T-t0) / nt # diferencia en tiempo&lt;br /&gt;
alpha = 1.0  # Coeficiente de difusión (para la ecuación del calor)&lt;br /&gt;
r = alpha * dt / (dx**2) #Coeficiente de estabilidad&lt;br /&gt;
&lt;br /&gt;
# Verificamos que se cumple la cond. de estabilidad para el esquema&lt;br /&gt;
if r &amp;gt; 0.5:&lt;br /&gt;
    raise ValueError(f&amp;quot;La condición de estabilidad no se cumple, 0.5 &amp;lt; {r=}&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo discretizado en x&lt;br /&gt;
x = np.linspace(0, L, nx)&lt;br /&gt;
&lt;br /&gt;
#Inicializamos el intervalo en t que vamos a emplear&lt;br /&gt;
t = np.linspace(t0, T, nt + 1)&lt;br /&gt;
&lt;br /&gt;
#Creamos el mallado en x y t:&lt;br /&gt;
X,T_mesh = np.meshgrid(x,t)&lt;br /&gt;
&lt;br /&gt;
# Inicializar la solución u(x, t) con ceros&lt;br /&gt;
u = np.zeros((nt + 1, nx))&lt;br /&gt;
&lt;br /&gt;
# Aplicamos las condiciones de frontera e inicial&lt;br /&gt;
u[:, 0] = 0&lt;br /&gt;
u[:, -1] = 0&lt;br /&gt;
u[0, :] = np.sin(2*np.pi*x)&lt;br /&gt;
&lt;br /&gt;
# Calculamos el índice del punto más cercano a x = 0.5&lt;br /&gt;
index_source = int(0.5 / dx)&lt;br /&gt;
&lt;br /&gt;
# Evolución temporal&lt;br /&gt;
for n in range(nt):&lt;br /&gt;
    u[n + 1, :] = u[n, :]  # Inicializar la siguiente iteración con los valores actuales&lt;br /&gt;
    for i in range(1, nx - 1):&lt;br /&gt;
        u[n + 1, i] = u[n, i] + r * (u[n, i + 1] - 2 * u[n, i] + u[n, i - 1])&lt;br /&gt;
    # Aproximación de la delta de Dirac&lt;br /&gt;
    u[n + 1, index_source] += 2 * dt / dx&lt;br /&gt;
&lt;br /&gt;
# Crear la figura y el subplot 3D&lt;br /&gt;
fig = plt.figure(figsize=(12, 8))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# Graficar la superficie, y añadimos etiquetas, barra de color, etc.&lt;br /&gt;
surf = ax.plot_surface(X, T_mesh, u, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('x')&lt;br /&gt;
ax.set_ylabel('t')&lt;br /&gt;
ax.set_zlabel('u(x, t)')&lt;br /&gt;
ax.set_title('Evolución temporal de la ecuación de calor con fuente (aproximación numérica)')&lt;br /&gt;
fig.colorbar(surf, ax=ax, label='u(x, t)')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Interpretación de la solución numérica y comparación con el caso sin fuente===&lt;br /&gt;
Los resultados numéricos muestran que efectivamente la fuente térmica localizada en &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; genera una acumulación de calor en su entorno inmediato. A medida que avanza el tiempo, se observa la disipación progresiva del calor debido a la difusión, que suaviza la temperatura alrededor de este punto, extendiéndola hacia el resto del dominio.&lt;br /&gt;
&lt;br /&gt;
En comparación con el caso sin fuente, donde la temperatura inicial se disipa homogéneamente y tiende a cero en todo el dominio, en este caso se observa un comportamiento diferente: la región en torno a &amp;lt;math&amp;gt; x_0 = 0.5 &amp;lt;/math&amp;gt; se mantiene significativamente más caliente durante más tiempo. Esto refleja el efecto de la fuente térmica puntual, que introduce energía de manera continua en el sistema, impidiendo que la temperatura disminuya de forma uniforme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84936</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84936"/>
				<updated>2025-03-18T22:33:39Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo MAMBD | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
'''Comparación con el caso sin fuente:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
'''Influencia de la intensidad y duración de la fuente:''' podemos analizar distintos valores de &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt; y ver cómo afectan la propagación térmica.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
En los casos sencillos de la ecuación del calor, como los vistos en clase, no existe aporte de calor a nuestro sistema o, si existe, es regular a lo largo del espacio y el tiempo. Podemos, sin embargo, tratar de estudiar el caso en el que se introduce una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto concreto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra de manera localizada, de manera que la ecuación del calor queda como sigue:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es de la forma &amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac, que hace que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Si consideramos &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt; y tomamos el mismo problema de la sección 2 con esta modificación, obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tratando de hallar una solución realizando la suposición de existencia de solución estacionaria, llegaríamos a una solución &amp;lt;math&amp;gt;u(x)&amp;lt;/math&amp;gt; que no sería continua. Es por ello que otros métodos algo más sofisticados son necesarios para resolver esta ecuación. La idea general, sin embargo, se encuentra en hallar las soluciones generales para nuestro problema homogéneo y, tras esto, describir &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; como suma de elementos de la base de Fourier que hayamos hallado. Debido a la facilidad con la que se integra &amp;lt;math&amp;gt;\delta(x)&amp;lt;/math&amp;gt;, esto no supondría un problema.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84933</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84933"/>
				<updated>2025-03-18T22:32:26Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo MAMBD | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
'''Comparación con el caso sin fuente:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
'''Influencia de la intensidad y duración de la fuente:''' podemos analizar distintos valores de &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt; y ver cómo afectan la propagación térmica.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
En los casos sencillos de la ecuación del calor, como los vistos en clase, no existe aporte de calor a nuestro sistema o, si existe, es regular a lo largo del espacio y el tiempo. Podemos, sin embargo, tratar de estudiar el caso en el que se introduce una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto concreto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra de manera localizada, de manera que la ecuación del calor queda como sigue:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es de la forma &amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac, que hace que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Si consideramos &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt; y tomamos el mismo problema de la sección 2 con esta modificación, obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tratando de hallar una solución realizando la suposición de existencia de solución estacionaria, llegaríamos a una solución &amp;lt;math&amp;gt;u(x)&amp;lt;/math&amp;gt; que no sería continua. Es por ello que otros métodos algo más sofisticados son necesarios para resolver esta ecuación. La idea general, sin embargo, se encuentra en hallar las soluciones generales para nuestro problema homogéneo y, tras esto, describir &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; como suma de elementos de la base de Fourier que hayamos hallado. Debido a la facilidad con la que se integra &amp;lt;math&amp;gt;\delta(x)&amp;lt;/math&amp;gt;, esto no supondría un problema.&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84924</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84924"/>
				<updated>2025-03-18T22:05:19Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo MAMBD | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
'''Comparación con el caso sin fuente:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
'''Influencia de la intensidad y duración de la fuente:''' podemos analizar distintos valores de &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt; y ver cómo afectan la propagación térmica.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
Hemos visto uno de los casos más sencillos de la difusión de calor, pero ahora se introduce una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra, de manera que la ecuación del calor queda como sigue:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es de la forma &amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;, donde &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac hacer que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Si consideramos &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt; y tomamos el mismo problema de la sección 2 con esta modificación, obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tratando de hallar una solución realizando la suposición de existencia de solución estacionaria, llegaríamos a una solución &amp;lt;math&amp;gt;u(x)&amp;lt;/math&amp;gt; que no sería continua. Es por ello que otros métodos algo más sofisticados son necesarios para resolver esta ecuación. La idea general, sin embargo, se encuentra en hallar las soluciones generales para nuestro problema homogéneo y, tras esto, describir &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; como suma de elementos de la base de Fourier que hayamos hallado. Debido a la facilidad con la que se integra &amp;lt;math&amp;gt;\delta(x)&amp;lt;/math&amp;gt;, esto no supondría un problema.&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84923</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84923"/>
				<updated>2025-03-18T22:04:51Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo MAMBD | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
'''Comparación con el caso sin fuente:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
'''Influencia de la intensidad y duración de la fuente:''' podemos analizar distintos valores de &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt; y ver cómo afectan la propagación térmica.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
Hemos visto uno de los casos más sencillos de la difusión de calor, pero ahora se introduce una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra, de manera que la ecuación del calor queda como sigue:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es de la forma &amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;, donde &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac hacer que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Si consideramos &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt; y tomamos el mismo problema de la sección 2 con esta modificación, obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tratando de hallar una solución realizando la suposición de existencia de solución estacionaria, llegaríamos a una solución &amp;lt;math&amp;gt;u(x)&amp;lt;\math&amp;gt; que no sería continua. Es por ello que otros métodos algo más sofisticados son necesarios para resolver esta ecuación. La idea general, sin embargo, se encuentra en hallar las soluciones generales para nuestro problema homogéneo y, tras esto, describir &amp;lt;math&amp;gt;f(x,t)&amp;lt;\math&amp;gt; como suma de elementos de la base de Fourier que hayamos hallado. Debido a la facilidad con la que se integra &amp;lt;math&amp;gt;\delta(x)&amp;lt;/math&amp;gt;, esto no supondría un problema.&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84920</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84920"/>
				<updated>2025-03-18T22:03:48Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo MAMBD | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
'''Comparación con el caso sin fuente:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
'''Influencia de la intensidad y duración de la fuente:''' podemos analizar distintos valores de &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt; y ver cómo afectan la propagación térmica.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
Hemos visto uno de los casos más sencillos de la difusión de calor, pero ahora se introduce una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra, de manera que la ecuación del calor queda como sigue:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es de la forma &amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;, donde &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac hacer que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Si consideramos &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt; y tomamos el mismo problema de la sección 2 con esta modificación, obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Tratando de hallar una solución realizando la suposición de existencia de solución estacionaria, llegaríamos a una solución &amp;lt;math&amp;gt;u(x)&amp;lt;\math&amp;gt; que no sería continua. Es por ello que otros métodos algo más sofisticados son necesarios para resolver esta ecuación. La idea general, sin embargo, se encuentra en hallar las soluciones generales para nuestro problema homogéneo y, tras esto, describir &amp;lt;math&amp;gt;f(x,t)&amp;lt;\math&amp;gt; como suma de elementos de la base de Fourier que hayamos hallado. Debido a la facilidad con la que se integra &amp;lt;math&amp;gt;\delta(x)&amp;lt;\math&amp;gt;, esto no supondría un problema.&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84919</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84919"/>
				<updated>2025-03-18T21:54:13Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo MAMBD | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
'''Comparación con el caso sin fuente:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
'''Influencia de la intensidad y duración de la fuente:''' podemos analizar distintos valores de &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt; y ver cómo afectan la propagación térmica.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\operatorname{sen}(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\operatorname{sen}(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
Hemos visto uno de los casos más sencillos de la difusión de calor, pero ahora se introduce una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra, de manera que la ecuación del calor queda como sigue:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es de la forma &amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;, donde &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac hacer que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Si consideramos &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt; y tomamos el mismo problema de la sección 2 con esta modificación, obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84918</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84918"/>
				<updated>2025-03-18T21:53:53Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo MAMBD | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
'''Comparación con el caso sin fuente:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
'''Influencia de la intensidad y duración de la fuente:''' podemos analizar distintos valores de &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt; y ver cómo afectan la propagación térmica.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\sen(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \sen(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\sen(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
Hemos visto uno de los casos más sencillos de la difusión de calor, pero ahora se introduce una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra, de manera que la ecuación del calor queda como sigue:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es de la forma &amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;, donde &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac hacer que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Si consideramos &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt; y tomamos el mismo problema de la sección 2 con esta modificación, obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \operatorname{sen}(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84917</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84917"/>
				<updated>2025-03-18T21:53:22Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: \sen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo MAMBD | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
'''Comparación con el caso sin fuente:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
'''Influencia de la intensidad y duración de la fuente:''' podemos analizar distintos valores de &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt; y ver cómo afectan la propagación térmica.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=\sen(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \sen(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=\sen(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
Hemos visto uno de los casos más sencillos de la difusión de calor, pero ahora se introduce una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra, de manera que la ecuación del calor queda como sigue:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es de la forma &amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;, donde &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac hacer que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Si consideramos &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt; y tomamos el mismo problema de la sección 2 con esta modificación, obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = \sen(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84916</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84916"/>
				<updated>2025-03-18T21:50:58Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo MAMBD | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
'''Comparación con el caso sin fuente:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
'''Influencia de la intensidad y duración de la fuente:''' podemos analizar distintos valores de &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt; y ver cómo afectan la propagación térmica.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=sen(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = sen(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=sen(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
Hemos visto uno de los casos más sencillos de la difusión de calor, pero ahora se introduce una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra, de manera que la ecuación del calor queda como sigue:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es de la forma &amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;, donde &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac hacer que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Al emplear la distribución &amp;lt;math&amp;gt;\delta&amp;lt;/math&amp;gt; de Dirac, estamos imponiendo que esta adición energética (calorífica) se encuentre extremadamente localizada, como la acción de un láser sobre una barra que simplificamos como unidimensional.&lt;br /&gt;
&lt;br /&gt;
Si consideramos &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt; y tomamos el mismo problema de la sección 2 con esta modificación, obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = sen(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84915</id>
		<title>Ecuación del calor (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Ecuaci%C3%B3n_del_calor_(Grupo_ILIA)&amp;diff=84915"/>
				<updated>2025-03-18T21:48:44Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Ecuación del calor. Grupo MAMBD | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Alicia Ruiz Dominguez, Luis Ramos Ortiz }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
La ecuación del calor es una de las ecuaciones en derivadas parciales más fundamentales en la física y las matemáticas aplicadas, modelando la difusión de la temperatura en distintos medios. Su estudio es esencial en múltiples disciplinas, desde la ingeniería térmica hasta la biomedicina, donde se analiza la propagación del calor en tejidos biológicos. En este trabajo, estudiaremos el comportamiento de esta ecuación en una barra unidimensional aislada en el intervalo [0,1], imponiendo condiciones de frontera con temperatura constante. &lt;br /&gt;
&lt;br /&gt;
En la vida real, las fuentes de calor no necesariamente tienen por qué estar en los extremos, por lo que también buscamos un enfoque más aplicado y realista. Nos enfocaremos en la propagación del calor cuando existe una fuente térmica localizada, es decir, introduciremos una fuente de calor puntual en algún punto en el interior de la barra (0,1) y veremos cómo se comporta la ecuación del calor. En la práctica, muchas aplicaciones incluyen fuentes térmicas, como calefactores, reacciones químicas o dispositivos electrónicos que generan calor; y esto tiene aplicaciones en procesos industriales, generación de energía y modelización de sistemas térmicos. &lt;br /&gt;
&lt;br /&gt;
En resumen, exploraremos cómo la presencia de una fuente de calor afecta a la distribución de la temperatura en el tiempo, resolviendo el problema tanto analíticamente como numéricamente. A través de esta aproximación, podremos comprender mejor la influencia de fuentes térmicas en sistemas difusivos y validar métodos numéricos para resolver ecuaciones en derivadas parciales. Estudiaremos varios aspectos:&lt;br /&gt;
&lt;br /&gt;
'''Ecuación del calor con fuente:''' en este caso, la ecuación incluye un término &amp;lt;math&amp;gt; f(x,t) &amp;lt;/math&amp;gt; que representa una generación de calor interna. Esto hace que la temperatura no solo se difunda, sino que también aumente o disminuya dependiendo de la fuente.&lt;br /&gt;
&lt;br /&gt;
'''Comparación con el caso sin fuente:''' veremos cómo la solución cambia al introducir un calentamiento localizado, observando si se alcanza un estado estacionario diferente o si la temperatura sigue variando en el tiempo.&lt;br /&gt;
&lt;br /&gt;
'''Influencia de la intensidad y duración de la fuente:''' podemos analizar distintos valores de &amp;lt;math&amp;gt; A &amp;lt;/math&amp;gt; y ver cómo afectan la propagación térmica.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor=&lt;br /&gt;
La ecuación de difusión del calor original sin fuentes de calor externas viene dada por:&lt;br /&gt;
&amp;lt;math&amp;gt;  &lt;br /&gt;
u_t=u_{xx}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
donde la función u(x,t) es la función temperatura en cada posición e instante de tiempo, &amp;lt;math&amp;gt;u_t&amp;lt;/math&amp;gt; la derivada temporal y &amp;lt;math&amp;gt;u_{xx}&amp;lt;/math&amp;gt; la segunda derivada espacial, que modela la difusión del calor.&lt;br /&gt;
&lt;br /&gt;
Si consideramos que la condición inicial en &amp;lt;math&amp;gt;t=0&amp;lt;/math&amp;gt; es &amp;lt;math&amp;gt;u(x,0)=sen(x)&amp;lt;/math&amp;gt;, podemos obtener el siguiente problema de ecuación del calor con condiciones frontera:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = 0, &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = sen(2\pi x), &amp;amp; x \in [0,1]&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Resolviendo este problema obtenemos que la solución estacionaria es:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_s(x)=0&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
y la solución general:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u(x,t)=sen(2\pi x)e^{-4\pi^{2}t}&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vamos a graficar la solución.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:soluil.png|400px|thumb|right|Solución de la ecuación del calor]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import numpy as np&lt;br /&gt;
import matplotlib.pyplot as plt&lt;br /&gt;
from mpl_toolkits.mplot3d import Axes3D&lt;br /&gt;
&lt;br /&gt;
# puntos de la malla&lt;br /&gt;
x = np.linspace(0, 1, 50)  &lt;br /&gt;
t = np.linspace(0, 0.5, 50)  &lt;br /&gt;
&lt;br /&gt;
X, T = np.meshgrid(x, t)  # malla&lt;br /&gt;
U = np.sin(2 * np.pi * X) * np.exp(-4 * np.pi**2 * T)  # sol general&lt;br /&gt;
&lt;br /&gt;
# figura&lt;br /&gt;
fig = plt.figure(figsize=(10, 6))&lt;br /&gt;
ax = fig.add_subplot(111, projection='3d')&lt;br /&gt;
&lt;br /&gt;
# grafica&lt;br /&gt;
ax.plot_surface(X, T, U, cmap='viridis')&lt;br /&gt;
ax.set_xlabel('Posición x')&lt;br /&gt;
ax.set_ylabel('Tiempo t')&lt;br /&gt;
ax.set_zlabel('Temperatura u(x,t)')&lt;br /&gt;
ax.set_title('Solución de la ecuación del calor')&lt;br /&gt;
&lt;br /&gt;
plt.show()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Como podemos ver la solución tiende rápidamente a la solución estacionaria en el que toda la barra está a 0 grados, que es lógico si tenemos en cuenta que los extremos tienen temperatura constante de 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Ecuación del calor con fuente térmica puntual=&lt;br /&gt;
Hemos visto uno de los casos más sencillos de la difusión de calor, pero ahora se introduce una función &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; que representa un nuevo foco de calor en un punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt; de la barra, de manera que la ecuación del calor queda como sigue:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;u_t = u_{xx}+f(x,t)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
Donde &amp;lt;math&amp;gt;f(x,t)&amp;lt;/math&amp;gt; es de la forma &amp;lt;math&amp;gt;f(x,t)=q(t)\delta(x-x_0)&amp;lt;/math&amp;gt;, donde &amp;lt;math&amp;gt;q(t)&amp;lt;/math&amp;gt; representa la cantidad de calor que se añade en función del tiempo y &amp;lt;math&amp;gt;\delta(x-x_0)&amp;lt;/math&amp;gt; es la delta de Dirac hacer que el calor se añada únicamente en el punto &amp;lt;math&amp;gt;x_0&amp;lt;/math&amp;gt;. Esto podría representar la adición de calor de manera muy localizada, casi infinitesimal, como la acción de un láser.&lt;br /&gt;
&lt;br /&gt;
Si consideramos &amp;lt;math&amp;gt;q(t)=2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_0=0.5&amp;lt;/math&amp;gt; y tomamos el mismo problema de la sección 2 con esta modificación, obtenemos el siguiente problema:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{cases}  &lt;br /&gt;
u_t - u_{xx} = f(x,t), &amp;amp; x \in [0,1], \quad t &amp;gt; 0 \\    &lt;br /&gt;
u(0,t) = 0, &amp;amp; t &amp;gt; 0 \\  &lt;br /&gt;
u(1,t) = 0, &amp;amp; t &amp;gt; 0 \\&lt;br /&gt;
u(x,0) = sen(2\pi x), &amp;amp; x \in [0,1] \\&lt;br /&gt;
f(x,t)=2\delta(x-0.5)&lt;br /&gt;
\end{cases}  &lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier_(Grupo_ILIA)&amp;diff=83904</id>
		<title>Series de Fourier (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier_(Grupo_ILIA)&amp;diff=83904"/>
				<updated>2025-02-13T07:32:05Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: Actualizado el código.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier (Grupo ILIA) | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Luis Ramos Ortiz, Alicia Ruiz Dominguez }}&lt;br /&gt;
&lt;br /&gt;
=Introducción=&lt;br /&gt;
&lt;br /&gt;
En una amplia gama de problemas de ingeniería y matemáticas aparecen funciones periódicas que se necesitan aproximar mediante sumas de funciones trigonométricas, lo que conduce a las '''series de Fourier'''.&lt;br /&gt;
&lt;br /&gt;
Estas series constituyen una herramienta fundamental en la resolución de ecuaciones en derivadas parciales y otros muchos ámbitos de la ciencia. La idea principal es que una función &amp;lt;math&amp;gt;f(x)&amp;lt;/math&amp;gt;, definida en un espacio de Hilbert &amp;lt;math&amp;gt;L^2(-\pi,\pi)&amp;lt;/math&amp;gt;, puede expresarse como una combinación infinita de funciones trigonométricas de la forma:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&lt;br /&gt;
f(x) \approx \frac{d_0}{2\pi} + \sum_{n=1}^{\infty}  d_n \frac{1}{\sqrt{\pi}} \cos(nx) + \sum_{n=1}^{\infty}c_n \frac{1}{\sqrt{\pi}} \sin(nx)&lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Los coeficientes &amp;lt;math&amp;gt;d_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;d_n&amp;lt;/math&amp;gt; y &amp;lt;math&amp;gt;c_n&amp;lt;/math&amp;gt; son los '''coeficientes de Fourier''' y se definen de la siguiente manera:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \quad&lt;br /&gt;
d_0 = \int_{-\pi}^{\pi} f(x) \frac{1}{\sqrt{\pi}} dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \quad&lt;br /&gt;
d_n = \int_{-\pi}^{\pi} f(x) \frac{1}{\sqrt{\pi}}cos(nx) dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; \quad&lt;br /&gt;
c_n = \int_{-\pi}^{\pi} f(x) \frac{1}{\sqrt{\pi}}sen(nx) dx&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Este método permite descomponer funciones periódicas en sus componentes fundamentales, lo que es de gran utilidad en física, ingeniería y matemáticas aplicadas. A continuación, se presentan las primeras funciones base utilizadas en la expansión en series de Fourier.&lt;br /&gt;
&lt;br /&gt;
=Base trigonométrica=&lt;br /&gt;
Para comprender mejor la construcción de las series de Fourier y poder visualizar las funciones base mencionadas, representamos gráficamente los primeros términos de la base trigonométrica &amp;lt;math&amp;gt; \mathcal{B} := \left\{ \frac{1}{2}, \cos(n\pi x), \sin(n\pi x) \right\}_{n \in \mathbb{N}} &amp;lt;/math&amp;gt; en el intervalo &amp;lt;math&amp;gt; [ -1, 1 ] &amp;lt;/math&amp;gt; mediante un código en Python. Esto nos permitirá observar cómo estas funciones elementales forman una '''base ortonormal''' en el espacio &amp;lt;math&amp;gt; L^2( [-1,1]) &amp;lt;/math&amp;gt; y cómo, mediante combinaciones lineales de estas, podemos aproximar funciones arbitrarias.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Archivo:GraficasILIA.jpeg|450px|thumb|right|Primeros términos de la Base Trigonométrica]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&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;
def base_fourier_cos(n: int) -&amp;gt; list[callable]:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Genera los n primeros términos de cosenos de la base trigonométrica de fourier&lt;br /&gt;
&lt;br /&gt;
    Args:&lt;br /&gt;
        n (int): Número de términos&lt;br /&gt;
&lt;br /&gt;
    Returns:&lt;br /&gt;
        list[callable]: lista con funciones lambda, ordenada según su posición en la base.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    basis_functions = []&lt;br /&gt;
    for k in range(1, n + 1):&lt;br /&gt;
        basis_functions.append(lambda x, k=k: np.cos(np.pi * k * x))&lt;br /&gt;
    return basis_functions&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def base_fourier_sen(n: int) -&amp;gt; list[callable]:&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;Genera los n primeros términos de senos de la base trigonométrica de fourier&lt;br /&gt;
&lt;br /&gt;
    Args:&lt;br /&gt;
        n (int): Número de términos&lt;br /&gt;
&lt;br /&gt;
    Returns:&lt;br /&gt;
        list[callable]: lista con funciones lambda, ordenada según su posición en la base.&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    basis_functions = []&lt;br /&gt;
    for k in range(1, n + 1):&lt;br /&gt;
        basis_functions.append(lambda x, k=k: np.sin(np.pi * k * x))&lt;br /&gt;
    return basis_functions&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Parámetros&lt;br /&gt;
X = np.linspace(-1, 1, 1000)&lt;br /&gt;
# número de elementos de la base (1, cos(n pi x), sen(n pi x))&lt;br /&gt;
n = 10&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
colors = colors = [&lt;br /&gt;
    &amp;quot;#0000FF&amp;quot;,&lt;br /&gt;
    &amp;quot;#0033CC&amp;quot;,&lt;br /&gt;
    &amp;quot;#0066CC&amp;quot;,&lt;br /&gt;
    &amp;quot;#0099FF&amp;quot;,&lt;br /&gt;
    &amp;quot;#33CCFF&amp;quot;,&lt;br /&gt;
    &amp;quot;#66CCCC&amp;quot;,&lt;br /&gt;
    &amp;quot;#CC9966&amp;quot;,&lt;br /&gt;
    &amp;quot;#FF6633&amp;quot;,&lt;br /&gt;
    &amp;quot;#FF3300&amp;quot;,&lt;br /&gt;
    &amp;quot;#FF0000&amp;quot;,&lt;br /&gt;
]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# Obtener funciones base&lt;br /&gt;
&lt;br /&gt;
base = [lambda x: 1] + base_fourier_cos(n) + base_fourier_sen(n)&lt;br /&gt;
&lt;br /&gt;
# Graficar&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
plt.subplots(3, 1, figsize=(15, 15), dpi=300)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
plt.subplot(3, 1, 1)&lt;br /&gt;
plt.grid()&lt;br /&gt;
plt.title(&amp;quot;Término constante&amp;quot;)&lt;br /&gt;
plt.plot([-1, 1], [1 / 2, 1 / 2], color=colors[-1], label=&amp;quot;Término constante&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
plt.subplot(3, 1, 2)&lt;br /&gt;
plt.grid()&lt;br /&gt;
plt.title(&amp;quot;Términos en coseno&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(1, n + 1):&lt;br /&gt;
    plt.plot(X, base[i](X), color=colors[i - 1], label=f&amp;quot;cos({str(i)*(i&amp;gt;1)}πx)&amp;quot;)&lt;br /&gt;
plt.legend(loc=&amp;quot;right&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
plt.subplot(3, 1, 3)&lt;br /&gt;
plt.grid()&lt;br /&gt;
plt.title(&amp;quot;Términos en seno&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for i in range(n + 1, len(base)):&lt;br /&gt;
    plt.plot(X, base[i](X), color=colors[i - n - 1], label=f&amp;quot;sen({str(i-n) * ((i-n) &amp;gt; 1)}πx)&amp;quot;)&lt;br /&gt;
plt.legend()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Al graficar estos términos, podemos apreciar cómo la combinación de estos elementos nos permite aproximar funciones periódicas arbitrarias, tal y como buscábamos.&lt;br /&gt;
La relevancia de esta base radica en su aplicación en la aproximación de funciones mediante series trigonométricas. En particular, la expansión de Fourier de una función \( f(x) \) en esta base se expresa como:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt; &amp;lt;math&amp;gt;&lt;br /&gt;
f(x) \approx \sum_{n=1}^{\infty} c_n e_n \quad \text{con} \quad c_n = \langle f, e_n \rangle&lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Donde \( e_n \) es cada uno de los términos de la base &amp;lt;math&amp;gt; \left\{ \frac{1}{2}, \cos(n\pi x), \sin(n\pi x) \right\}_{n \in \mathbb{N}} &amp;lt;/math&amp;gt;, y &amp;lt;math&amp;gt; c_n &amp;lt;/math&amp;gt; son los coeficientes que se calculan mediante el producto interno de &amp;lt;math&amp;gt; f(x) &amp;lt;/math&amp;gt; con los elementos de la base.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Como se puede observar, a medida que el parámetro &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt; aumenta, los términos oscilan con un periodo cada vez menor, concretamente &amp;lt;math&amp;gt; T = \frac{2}{n} &amp;lt;/math&amp;gt;, lo que refleja una mayor &amp;quot;frecuencia&amp;quot; en las oscilaciones. Esta característica es esencial en la aproximación de funciones suaves por medio de las series de Fourier, donde las funciones periódicas se aproximan cada vez con mayor precisión mediante una combinación lineal de estos términos básicos.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Categoría:EDP]]&lt;br /&gt;
[[Categoría:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	<entry>
		<id>https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier_(Grupo_ILIA)&amp;diff=83796</id>
		<title>Series de Fourier (Grupo ILIA)</title>
		<link rel="alternate" type="text/html" href="https://mat.caminos.upm.es/w/index.php?title=Series_de_Fourier_(Grupo_ILIA)&amp;diff=83796"/>
				<updated>2025-02-12T18:20:21Z</updated>
		
		<summary type="html">&lt;p&gt;Nacho: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ TrabajoED | Series de Fourier (Grupo ILIA) | [[:Categoría:EDP|EDP]]|[[:Categoría:EDP24/25|2024-25]] | Ignacio Campos Paños, Ignacio Martínez Cerezo, Luis Ramos Ortiz, Alicia Ruiz Dominguez }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Onichaan.&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:EDP24/25]]&lt;/div&gt;</summary>
		<author><name>Nacho</name></author>	</entry>

	</feed>