···11+%% =========================================================================
22+%
33+% Modelo FDTD de una columna de altavoces direccionable.
44+%
55+% Se incluyen 3 puntos de recepci�n.
66+%
77+% Jose Manuel Requena Plens (16/03/2020)
88+%
99+% =========================================================================
1010+clc, clear, close all;
1111+% Version de la columna donde se maximiza la eficiencia en el punto de
1212+% escucha optimizando inclinacion y curvatura
1313+1414+%% GENERAL
1515+% Caracteristicas del medio
1616+rho = 1.21; % Densidad del medio (kg/m3)
1717+c = 341; % Velocidad de propagaci�n (m/s)
1818+k = (c^2)*rho; % Modulo de compresibilidad
1919+% Frecuencia de emision
2020+freq = 4000; % (Hz)
2121+% Tipo de excitaci�n ('pulse' o 'CW')
2222+excit = 'CW';
2323+% Dimensiones del mapa en metros
2424+lx = 5; % m
2525+ly = 3; % m
2626+% Columna
2727+N = 32; % Numero de elementos de la columna
2828+d = 0.04; % Distancia entre elementos (de centro a centro) (m)
2929+Origen = [1,2.5]; % Posicion de origen de la columna (m,m)
3030+% Punto de escucha
3131+Foco = [4,0.5];
3232+% Posicion de los receptores
3333+rec1 = [4,0.25]; % Posicion del receptor 1 (m,m)
3434+rec2 = [1,0.25];% Posicion del receptor 2 (m,m)
3535+rec3 = [lx-1,Origen(2)-(N-1)*d/2]; % Receptor a 0 grados
3636+% Tama�o/Ancho de la PML en metros
3737+lPML = 0.25; % m
3838+% Par�metros de calculo
3939+dh = .01; % Definici�n espacial (m)
4040+dt = dh/341/2; % Definici�n temporal (s)
4141+ts = 15; % Tiempo de simulaci�n (ms)
4242+4343+%% MATRICES
4444+% Dimensiones de la matriz del mapa
4545+nPML = round(lPML/dh);
4646+nx = round(lx/dh)+nPML*2; % Por 2 ya que la PML esta arriba y abajo
4747+ny = round(ly/dh)+nPML*2; % Por 2 ya que la PML esta a izquierda y derecha
4848+% Crear matriz del mapa
4949+p = zeros(nx,ny); % Matrices de presion
5050+px = zeros(nx,ny);
5151+py = zeros(nx,ny);
5252+ux = zeros(nx+1,ny); % Matriz de velocidad de particula en x
5353+uy = zeros(nx,ny+1); % Matriz de velocidad de particula en y
5454+5555+%% POSICIONES DE LOS ELEMENTOS
5656+% Posiciones de los elementos en la matriz del mapa
5757+posNy = round((Origen(2)-(0:N-1) * d)/dh) + nPML;
5858+posNx = round(Origen(1)/dh) + nPML;
5959+6060+%% C�LCULO DE LOS RETARDOS TEMPORALES (dly)
6161+% Calculo del angulo para emitir hacia el punto de escucha
6262+theta = -rad2deg(atan((Origen(2)-d*N/2-Foco(2)+lPML)/(Foco(1)-Origen(1))));
6363+% Inclinaci�n
6464+x = sin(-theta*pi/180)*d; % Calculo de distancia simulada del segundo elemento
6565+D = x * (0:N-1)'; % Vector de distancias para cada elemento (de arriba a abajo)
6666+dlytilt = D/c; % Vector de tiempos/delays para cada elemento por la inclinacion
6767+6868+% Calculo de la distancia desde el origen de la columna (centro de la
6969+% columna inclinada) hasta el punto de escucha para utilizarlo de radio
7070+% para la focalizaci�n
7171+rarc = -sqrt((Foco(1)-(Origen(1)-D(round(N/2))))^2+(Foco(2)-(Origen(2)-d*N/2))^2);
7272+% Arco
7373+thetaarc = linspace(-pi/2-deg2rad(-theta), pi/2-deg2rad(-theta), 1000); % Vector de angulos para una semicircunferencia
7474+Ltot = (N-1)*d; % Longitud total de la columna
7575+% Semicircunferencia
7676+x = (rarc * cos(thetaarc) + Origen(1)-rarc);
7777+y = (rarc * sin(thetaarc) + Origen(2)-Ltot/2);
7878+% Distancias
7979+Darc = zeros(N,1);
8080+for m = 1:N
8181+ [~,idx]=min(abs(y-(Origen(2)-(m-1)*d)));
8282+ Darc(m) = Origen(1)-abs(x(idx));
8383+end
8484+dlyarc = Darc/c; % Vector de tiempos/delays producidos por arquear
8585+8686+% Vector de delays
8787+dly = dlyarc+dlytilt;
8888+8989+% Representacion de las fuentes virtuales frente a la real
9090+% posVirtual = zeros(N,2);
9191+% for m = 1:N
9292+% posVirtual(m,:) = [Origen(1)-D(m)-Darc(m),Origen(2)-(m-1)*d+lPML];
9393+% end
9494+% figb = figure('Color',[1,1,1]);
9595+% plot(posVirtual(:,1),posVirtual(:,2),'ro', 'MarkerSize', 2,'MarkerFaceColor','r')
9696+% hold on
9797+% plot((ones(size(posNy))*posNx-nPML)*dh,posNy*dh,'ko', 'MarkerSize', 2,'MarkerFaceColor','k')
9898+% axis equal,grid on
9999+% axis([0,lx,0,ly])
100100+% title('Posici�n de las fuentes')
101101+% xlabel('X [m]'),ylabel('Y [m]')
102102+% legend('Virtual','Real')
103103+104104+%% EXCITACI�N (la misma se�al con diferente retardo para cada elemento)
105105+% El retardo se aplica en el vector 't'
106106+lenT = ts*10^-3/dt; % Longitud del vector de tiempo
107107+aa = freq/(sqrt(pi)/2)*4;
108108+t=((1:lenT)/(1/dt)-4/aa); % Vector de tiempos
109109+w = zeros(lenT,N);
110110+for n = 1:N
111111+ % Funcion que define la excitacion, una para cada n, se incluye el
112112+ % retardo para cada elemento
113113+ switch excit
114114+ case 'pulse'
115115+ w(:,n) = -(exp(-aa^2*((t-dly(n)).^2)/2).*(aa^2*((t-dly(n)).^2)-1)); % Impulso / Ricker con retardo
116116+ case 'CW'
117117+ w(:,n) = cos(2*pi*freq*t)+1i*sin(2*pi*freq*t); % Seno complejo
118118+ % Retardo aplicado
119119+ w(:,n) = w(:,n).*exp(dly(n).*-1j*2*pi*freq);
120120+ end
121121+end
122122+123123+%% PML
124124+% Gradiente de impedancias desde el valor del medio hasta un porcentaje de
125125+% este
126126+gammamax = 0.5; % Maxima reducci�n de la impedancia / porcentaje
127127+% PML Superior e Inferior
128128+gammaux = zeros(nx+1,ny);
129129+gammaux(1:nPML,:) = repmat(gammamax*((nPML:-1:1)'/nPML).^2,1,ny); % Izquierda
130130+gammaux(1+end-nPML:end,:) = repmat(gammamax*((1:1:nPML)'/nPML).^2,1,ny); % Derecha
131131+gammax = (gammaux(1:end-1,:)+gammaux(2:end,:))/2; % Conjunto
132132+% PML Izquierda y Derecha
133133+gammauy = zeros(nx,ny+1);
134134+gammauy(:,1:nPML) = repmat(gammamax*((nPML:-1:1)/nPML).^2,nx,1); % Inferior
135135+gammauy(:,1+end-nPML:end) = repmat(gammamax*((1:1:nPML)/nPML).^2,nx,1); % Superior
136136+gammay = (gammauy(:,1:end-1)+gammauy(:,2:end))/2; % Conjunto
137137+138138+%% Inicializacion de los vectores de los puntos de escucha
139139+h = zeros(1,lenT);
140140+h2 = zeros(1,lenT);
141141+h3 = zeros(1,lenT);
142142+143143+%% Condiciones de contorno
144144+ux(1,:) = -p(1,:)/rho/c;
145145+ux(end,:) = p(end,:)/rho/c;
146146+uy(:,1) = -p(:,1)/rho/c;
147147+uy(:,end) = p(:,end)/rho/c;
148148+149149+%% Calculo
150150+fig1 = figure('Color',[1,1,1]);
151151+152152+colormap(jet(256))
153153+for tt=1:lenT
154154+ % Presion
155155+ px = px.*(1-gammax)-k*dt/dh*diff(ux);
156156+ py = py.*(1-gammay)-k*dt/dh*diff(uy')';
157157+158158+ % Excitaci�n
159159+ for n = 1:N
160160+ px(posNx,posNy(n)) = w(tt,n);
161161+ py(posNx,posNy(n)) = w(tt,n);
162162+ end
163163+ p = px+py;
164164+165165+ % Velocidad
166166+ ux(2:nx,:) = ux(2:nx,:).*(1-gammaux(2:nx,:))-dt/rho/dh*diff(p);
167167+ uy(:,2:ny) = uy(:,2:ny).*(1-gammauy(:,2:ny))-dt/rho/dh*diff(p')';
168168+169169+ % Respuesta al impulso
170170+ h(tt) = p(round(rec1(1)/dh)+nPML,round(rec1(2)/dh)+nPML);
171171+ h2(tt) = p(round(rec2(1)/dh)+nPML,round(rec2(2)/dh)+nPML);
172172+ h3(tt) = p(round(rec3(1)/dh)+nPML,round(rec3(2)/dh)+nPML);
173173+174174+ % Representaci�n gr�fica
175175+ if tt/10==round(tt/10)
176176+ splmap = 10*log10(abs(p).^2/(2e-5)^2);
177177+ %splmap = splmap - max(splmap(:));
178178+ pcolor(((1:nx)-nPML)*dh,((1:ny)-nPML)*dh,splmap');
179179+ hold on;
180180+ plot([0,0,nx-2*nPML,nx-2*nPML,0]*dh,[0,ny-2*nPML,ny-2*nPML,0,0]*dh,'r--','linewidth',2)
181181+ plot(repmat(posNx-nPML,1,N)*dh,(posNy-nPML)*dh, 'wo', 'MarkerSize', 2,'MarkerFaceColor','w');
182182+ plot([rec1(1),rec2(1),rec3(1)],[rec1(2),rec2(2),rec3(2)], 'bo', 'MarkerSize', 4,'MarkerFaceColor','b');
183183+ text([rec1(1),rec2(1),rec3(1)]+0.05,[rec1(2),rec2(2),rec3(2)],{'Rec1','Rec2','Rec3'},'Color','white')
184184+ hold off
185185+ axis equal;axis([-nPML,nx-nPML,-nPML,ny-nPML]*dh)
186186+ set(gca,'Clim',[50 110]);shading flat,cc = colorbar;
187187+ title(['Tiempo = ' num2str(round((tt)*1000*dt)) ' ms']);
188188+ xlabel('X [m]'),ylabel('Y [m]'),cc.Label.String = 'SPL (dB)';
189189+ drawnow
190190+ end
191191+end
192192+% Respuesta al impulso / Punto de escucha
193193+time = seconds(t);
194194+maxx = max([abs(h),abs(h2),abs(h3)]);
195195+h = h./maxx; h2 = h2./maxx; h3 = h3./maxx;
196196+T = array2timetable([h',h2',h3'],...% Datos iniciales
197197+'RowTimes',time); % Columna de tiempo
198198+fig= figure('Color',[1,1,1]);
199199+s = stackedplot(T,...
200200+ 'Title','Se�al recibida',...
201201+ 'DisplayLabels',{'Receptor 1', 'Receptor 2', 'Receptor 3'},...
202202+ 'XLabel','Se�al recibida');
203203+s.GridVisible = 1;
204204+s.AxesProperties(1).YLimits = [-1.2,1.2];
205205+s.AxesProperties(2).YLimits = [-1.2,1.2];
206206+s.AxesProperties(3).YLimits = [-1.2,1.2];
207207+fig.Children.FontName = 'Arial';
208208+fig.Children.FontSize = 12;