···11+%% =========================================================================
22+%
33+% Modelo simple de FDTD de un recinto en 2D con excitaci�n Ricker y PML
44+%
55+% Se incluyen 3 puntos de recepci�n y un ejemplo b�sico para introducir
66+% objetos rigidos que interactuan con el campo ac�stico.
77+%
88+% Jose Manuel Requena Plens (09/09/2019)
99+%
1010+% =========================================================================
1111+clc, clear, close all;
1212+1313+%% GENERAL
1414+% Caracteristicas del medio
1515+rho = 1.21; % Densidad del medio [kg/m3]
1616+c = 341; % Velocidad de propagaci�n [m/s]
1717+K = (c^2)*rho; % Modulo de compresibilidad
1818+% Dimensiones del mapa en metros
1919+lx = 5; % Ancho [m]
2020+ly = 3; % Alto [m]
2121+%
2222+Origen = [1,2.5]; % Origen de la fuente
2323+% Posicion de los receptores
2424+rec1 = [4,0.25]; % Posicion del receptor 1 [m,m]
2525+rec2 = [1,0.25];% Posicion del receptor 2 [m,m]
2626+rec3 = [2,2]; % Posicion del receptor 3 [m,m]
2727+% Tama�o/Ancho de la PML en metros
2828+lPML = 0.25; % m
2929+% Par�metros de calculo
3030+dh = .01; % Definici�n espacial [m]
3131+dt = dh/341/2; % Definici�n temporal [s]
3232+ts = 15; % Tiempo de simulaci�n [ms]
3333+3434+%% MATRICES
3535+% Dimensiones de la matriz del mapa
3636+nPML = round(lPML/dh);
3737+nx = round(lx/dh)+nPML*2; % Por 2 ya que la PML esta arriba y abajo
3838+ny = round(ly/dh)+nPML*2; % Por 2 ya que la PML esta a izquierda y derecha
3939+% Crear matriz del mapa
4040+p = zeros(nx,ny); % Matrices de presion
4141+px = zeros(nx,ny);
4242+py = zeros(nx,ny);
4343+ux = zeros(nx+1,ny); % Matriz de velocidad de particula en x
4444+uy = zeros(nx,ny+1); % Matriz de velocidad de particula en y
4545+4646+%% POSICIONES DE LA FUENTE
4747+%
4848+posNy = round((Origen(2))/dh) + nPML;
4949+posNx = round(Origen(1)/dh) + nPML;
5050+5151+5252+%% EXCITACI�N
5353+lenT = ts*10^-3/dt; % Longitud del vector de tiempo
5454+a = 2000/(sqrt(pi)/2)*4;
5555+t=((1:lenT)/(1/dt)-4/a); % Vector de tiempos
5656+w=-(exp(-a^2*(t.^2)/2).*(a^2*(t.^2)-1)); % Ricker
5757+5858+%% PML
5959+% Gradiente de impedancias desde el valor del medio hasta un porcentaje de
6060+% este
6161+gammamax = 0.5; % Maxima reducci�n de la impedancia / porcentaje
6262+% PML Izquierda y derecha
6363+gammaux = zeros(nx+1,ny);
6464+gammaux(1:nPML,:) = repmat(gammamax*((nPML:-1:1)'/nPML).^2,1,ny); % Izquierda
6565+gammaux(1+end-nPML:end,:) = repmat(gammamax*((1:1:nPML)'/nPML).^2,1,ny); % Derecha
6666+gammax = (gammaux(1:end-1,:)+gammaux(2:end,:))/2; % Conjunto
6767+% PML Superior e inferior
6868+gammauy = zeros(nx,ny+1);
6969+gammauy(:,1:nPML) = repmat(gammamax*((nPML:-1:1)/nPML).^2,nx,1); % Inferior
7070+gammauy(:,1+end-nPML:end) = repmat(gammamax*((1:1:nPML)/nPML).^2,nx,1); % Superior
7171+gammay = (gammauy(:,1:end-1)+gammauy(:,2:end))/2; % Conjunto
7272+7373+%% Inicializacion de los vectores de los puntos de escucha
7474+h = zeros(1,lenT);
7575+h2 = zeros(1,lenT);
7676+h3 = zeros(1,lenT);
7777+7878+%% Condiciones de contorno
7979+ux(1,:) = -p(1,:)/rho/c;
8080+ux(end,:) = p(end,:)/rho/c;
8181+uy(:,1) = -p(:,1)/rho/c;
8282+uy(:,end) = p(:,end)/rho/c;
8383+8484+%% Calculo
8585+fig1 = figure('Color',[1,1,1]);
8686+8787+colormap(jet(256))
8888+for tt=1:lenT
8989+ % Presion
9090+ px = px.*(1-gammax)-K*dt/dh*diff(ux);
9191+ py = py.*(1-gammay)-K*dt/dh*diff(uy')';
9292+9393+ % Excitaci�n
9494+ px(posNx,posNy) = w(tt);
9595+ py(posNx,posNy) = w(tt);
9696+ p = px+py;
9797+9898+ % Velocidad
9999+ ux(2:nx,:) = ux(2:nx,:).*(1-gammaux(2:nx,:))-dt/rho/dh*diff(p);
100100+ uy(:,2:ny) = uy(:,2:ny).*(1-gammauy(:,2:ny))-dt/rho/dh*diff(p')';
101101+102102+ % Objetos (Se puede eliminar o modificar sin introducir valores fuera
103103+ % de las dimensiones del mapa)
104104+ % Barrera de 30cm de ancho
105105+ orX = 1; % Origen en X
106106+ orY = 0; % Origen en Y
107107+ wid = 0.3; % Ancho de la barrera
108108+ hei = 1.5; % Altura de la barrera
109109+ vecX = (round(orX/dh):round((orX+wid)/dh))+nPML;
110110+ vecY = (round(orY/dh)+1:round(hei/dh))+nPML;
111111+ ux(vecX,vecY) = 0;
112112+ uy(vecX,vecY) = 0;
113113+114114+ % Respuesta al impulso
115115+ h(tt) = p(round(rec1(1)/dh)+nPML,round(rec1(2)/dh)+nPML);
116116+ h2(tt) = p(round(rec2(1)/dh)+nPML,round(rec2(2)/dh)+nPML);
117117+ h3(tt) = p(round(rec3(1)/dh)+nPML,round(rec3(2)/dh)+nPML);
118118+119119+ % Representaci�n gr�fica
120120+ if tt/10==round(tt/10)
121121+ splmap = 10*log10(abs(p).^2/(2e-5)^2);
122122+ %splmap = splmap - max(splmap(:));
123123+ pcolor(((1:nx)-nPML)*dh,((1:ny)-nPML)*dh,splmap');
124124+ hold on;
125125+ plot([0,0,nx-2*nPML,nx-2*nPML,0]*dh,[0,ny-2*nPML,ny-2*nPML,0,0]*dh,'r--','linewidth',2)
126126+ plot([rec1(1),rec2(1),rec3(1)],[rec1(2),rec2(2),rec3(2)], 'ro', 'MarkerSize', 2,'MarkerFaceColor','r');
127127+ text([rec1(1),rec2(1),rec3(1)]+0.05,[rec1(2),rec2(2),rec3(2)],{'Rec1','Rec2','Rec3'},'Color','white')
128128+ hold off
129129+ axis equal;axis([-nPML,nx-nPML,-nPML,ny-nPML]*dh)
130130+ set(gca,'Clim',[50 110]);shading flat,cc = colorbar;
131131+ title(['Tiempo = ' num2str(round((tt)*1000*dt)) ' ms']);
132132+ xlabel('X [m]'),ylabel('Y [m]'),cc.Label.String = 'SPL (dB)';
133133+ drawnow
134134+ end
135135+end
136136+137137+% Respuesta al impulso / Punto de escucha
138138+time = seconds(t);
139139+maxx = max([abs(h),abs(h2),abs(h3)]);
140140+h = h./maxx; h2 = h2./maxx; h3 = h3./maxx;
141141+T = array2timetable([h',h2',h3'],...% Datos iniciales
142142+'RowTimes',time); % Columna de tiempo
143143+fig= figure;
144144+s = stackedplot(T,...
145145+ 'Title','Se�al recibida',...
146146+ 'DisplayLabels',{'Receptor 1', 'Receptor 2', 'Receptor 3'},...
147147+ 'XLabel','Se�al recibida');
148148+s.GridVisible = 1;
149149+s.AxesProperties(1).YLimits = [-1.2,1.2];
150150+s.AxesProperties(2).YLimits = [-1.2,1.2];
151151+s.AxesProperties(3).YLimits = [-1.2,1.2];
152152+fig.Children.FontName = 'Arial';
153153+fig.Children.FontSize = 12;