MC4: Introdução à Programação Paralela em GPU para a Implementação de Métodos Numéricos Aula 3: Solução de EDPs Método FDTD (Finite-Difference Time-Domain Method) para as equações de Maxwell 22 de setembro de 2017
Section 1 Equações de Maxwell
Motivação Equações de Maxwell As ondas eletromagnéticas possuem diversas aplicações, como por exemplo nas tecnologias de comunicação sem fio e em alguns tipos de tratamentos e diagnósticos na área médica. O desenvolvimento e aprimoramento dessas aplicações requerem um estudo detalhado da interação do campo eletromagnético e a propagação de ondas eletromagnéticas.
Motivação Equações de Maxwell Esse estudo toma como base as equações de Maxwell, um sistema de equações em derivadas parciais que descreve a evolução das ondas eletromagnéticas. A implementação dos métodos numéricos para a resolução dessas equações é computacionalmente desafiadora quando precisamos modelar tempos de propagação longos.
Equações de Maxwell Forma diferencial H t = 1 µ E 1 µ ( M fonte + σ H) E t = 1 ɛ H 1 ɛ ( J fonte + σ E) H e E campos magnético e elétrico; M fonte e J fonte fontes magnéticas e elétricas; µ permeabilidade magnética; ɛ permissividade elétrica; σ condutividade elétrica; σ perda magnética equivalente. Condições de contorno componente tangencial de H e/ou E (Dirichlet); condição de radiação de Sommerfeld (região ilimitada).
Modo transversal elétrico TE z Considerando que os campos não dependem da variável z, obtemos H z t E x t E y t = 1 ( Ex µ y E y = 1 ( ) Hz ε y (J x + σe x ), = 1 ( H ) z ε x (J y + σe y ). ) x (M z + σ H z ) As restantes componentes dos campos satisfazem um sistema semelhante conhecido como modo transversal magnético TM z.,
Section 2
: malha
: avanço no tempo H z n+1 i;j E x n+ 3 2 i;j+ 1 2 = ah z n i;j + b = ce x n+ 1 2 + d i;j+ 1 2 E y n+ 3 2 i+ 1 2 ;j = ce y n+ 1 2 i+ 1 2 ;j + d E x n+ 1 2 E i;j+ 1 x n+ 1 2 i;j 1 2 2 y E y n+ 1 2 i+ 1 2 ;j E y n+ 1 2 i 1 2 ;j x { Hz n+1 i;j+1 H z n+1 i;j y { M z n+ 1 2 i;j J x n+1 i;j+ 1 2 } H z n+1 i+1;j H z n+1 i;j J y n+1 x i+ 1 2 ;j }
: avanço no tempo em que a = 1 σ t 2µ, b = 1 + σ t 2µ c = 1 σ t 2ɛ 1 + σ t, d = 2ɛ t µ 1 + σ t 2µ t ɛ 1 + σ t 2ɛ constantes associadas com as propriedades do meio.,
: avanço no tempo
: condição CFL Para a estabilidade numérica, o tamanho do passo do tempo deve satisfazer a condição de estabilidade de Courant-Friedrichs-Lewy (CFL) 1 t, υ 1 + 1 x 2 y 2 υ = 1/ ɛµ velocidade de propagação das ondas eletromagnéticas.
Fluxograma correspondente ao esquema de Yee
Section 3
Ideia básica Realizar o controle do avanço no tempo na CPU Lançar em cada passo vários kernels para introduzir as condições de contorno; incluir as fontes; atualizar os campos H z, E x e E y. Atualizar cada campo em paralelo, associando a cada thread um único ponto da malha. Os blocos da grade de threads precisam cobrir todos os pontos da malha
Exemplo implementado Simplificações região retangular; estado inicial de repouso; a fronteira da região é um condutor perfeito; uma fonte magnética atuando em um único ponto; condições de contorno: condutor elétrico perfeito (E x = 0 ou E y = 0). É preciso implementar somente os kernels para a atualização dos campos elétrico e magnético.
Observações Equações de Maxwell Nas equações discretizadas as componentes do campo estão associadas com índices espaciais da forma (i, j) (i ± 1/2, j) e (i, j ± 1/2) em que i, j são inteiros. Para ordenar dos dados, associamos os índices (i + 1/2, j) e (i, j + 1/2) com o índice (i, j). Os índices (i, j) da malha ficam restringidos ao conjunto 0 i < N x e 0 j < N y onde N x, N y são dois inteiros positivos que definem as dimensões da malha. As componentes u i,j (u = E x, E y ou H z ) associadas com os pontos (i, j) da malha são armazenados como um vetor usando o indice I = i N y + j. A malha para as componentes E x e E y tem uma coluna e uma linha a menos que a malha de H z, respectivamente.
Kernel para a atualização de H z global void atualiza_h(double *d_ex, double *d_ey, double *d_hz, double c_a, double c_b, int nx, int ny, double dx, double dy, int i_f, int j_f, double val_f ) { int i=blockidx.x*blockdim.x+threadidx.x; int j=blockidx.y*blockdim.y+threadidx.y; double DyEx = 0, DxEy = 0; if (i < nx && j < ny) { //n~ao está na borda esquerda if (i > 0) { DxEy -= d_ey[ (i-1)*ny + j ]; }
Kernel para a atualização de H z (cont) //n~ao está na borda direita if (i < nx-1) { DxEy += d_ey[ i*ny + j ]; } //n~ao está na borda inferior if (j > 0) { DyEx -= d_ex[ i*(ny-1) + j-1 ]; } //n~ao está na borda superior if (j < ny-1) { DyEx += d_ex[ i*(ny-1) + j ]; }
Kernel para a atualização de H z (cont) d_hz[i*ny+j] = c_a*d_hz[i*ny+j] + c_b*( DyEx/dy - DxEy/dx ); } } //influ^encia da fonte if (i == i_f && j == j_f) { d_hz[i*ny+j] = val_f; }
Kernel para a atualização de E x e E y global void atualiza_e(double *d_ex, double *d_ey, double *d_hz, double c_c, double c_d, int nx, int ny, double dx, double dy){ int i=blockidx.x*blockdim.x+threadidx.x; int j=blockidx.y*blockdim.y+threadidx.y; double DyHz, DxHz; if (i < nx && j < ny) { DxHz= -d_hz[i*ny+j]; DyHz = DxHz;
Kernel para a atualização de E x e E y (cont) //n~ao tem Ex acima da borda superior if (j < ny-1) { DyHz += d_hz[ i*ny + (j+1) ]; d_ex[i*(ny-1)+j] = c_c*d_ex[i*(ny-1)+j] + c_d*dyhz/dy; } } } //n~ao tem Ey à direita da borda direita if (i < nx-1) { DxHz += d_hz[ (i+1)*ny + j ]; d_ey[i*ny+j] = c_c*d_ey[ i*ny+j ]-c_d*dxhz/dx; }
Modelo de função main() int main() { //par^ametros dos blocos de threads int TAM_B_x, TAM_B_y; TAM_B_x = 32; TAM_B_y = 32; double eps=1, mu=1, sigma1=0, sigma2=0; double x_ini,x_final,y_ini,y_final,t_ini,t_final; double x_fonte, y_fonte; int nx, ny, n_passos; double dx, dy, dt; double c_a, c_b, c_c, c_d;
Modelo de função main() (cont) dx = (x_final-x_ini)/nx; dy = (y_final-y_ini)/ny; dt = (t_final-t_ini)/n_passos; //cálculo dos coeficientes constantes c_a = (1-0.5*sigma2*dt/mu)/(1+0.5*sigma2*dt/mu); c_b = (dt/mu)/(1+0.5*sigma2*dt/mu); c_c = (1-0.5*sigma1*dt/eps)/(1+0.5*sigma1*dt/eps); c_d = (dt/eps)/(1+0.5*sigma1*dt/eps); //índice da posiç~ao da fonte na malha int i_f, j_f; i_f = (int)((x_fonte-x_ini)/dx); j_f = (int)((y_fonte-y_ini)/dy);
Modelo de função main() (cont) //vetores para inicializar e salvar os resultados double *Hz, *Ex, *Ey; size_t dim_hz = nx*ny, dim_ex=nx*(ny-1), dim_ey=(nx-1)*ny; //adicionar código para as condiç~oes iniciais //alocar memória na GPU para os vetores dos campos double* d_hz, *d_ex, *d_ey; CUDA_SAFE_CALL( cudamalloc( (void**) &d_hz, dim_hz*sizeof(double) )); CUDA_SAFE_CALL( cudamalloc( (void**) &d_ex, dim_ex*sizeof(double) )); CUDA_SAFE_CALL( cudamalloc( (void**) &d_ey, dim_ey*sizeof(double) ));
Modelo de função main() (cont) //transferir os dados para a GPU CUDA_SAFE_CALL( cudamemcpy(d_hz, Hz, dim_hz*sizeof(double), cudamemcpyhosttodevice)); CUDA_SAFE_CALL( cudamemcpy(d_ex, Ex, dim_ex*sizeof(double), cudamemcpyhosttodevice)); CUDA_SAFE_CALL( cudamemcpy(d_ey, Ey, dim_ey*sizeof(double), cudamemcpyhosttodevice)); //definir a grade de blocos int g_x= (nx + TAM_B_x-1)/TAM_B_x; int g_y= (ny + TAM_B_y-1)/TAM_B_y; dim3 dim_bloco(tam_b_x,tam_b_y); dim3 dim_grade(g_x,g_y);
Modelo de função main() (cont) //laço para iteraç~ao no tempo for (i_t=0; i_t<n_passos; i_t++ ) { //adicionar o código que calcula a fonte val_f =... ; atualiza_h<<< dim_grade,dim_bloco>>>(d_ex,d_ey,d_hz, c_a,c_b,nx,ny,dx,dy,i_f,j_f,val_f ); atualiza_e<<< dim_grade,dim_bloco>>>(d_ex,d_ey,d_hz, c_c,c_d,nx,ny,dx,dy); //adicionar código para usar os resultados } // liberar a memória da GPU e da CPU... // liberar a GPU... }
Section 4
Métricas usadas Equações de Maxwell Usamos as métricas de tempo de execução, aceleração e vazão (ou velocidade). A vazão foi calculada em milhões de celas por segundo [MCells/s] a partir da equação vazão = N x N y N t 10 6 T e N x e N y dimensões da malha utilizada para a discretização; N t número de passos no tempo; T e tempo de execução da implementação medido em segundos.
Testes Equações de Maxwell Condições de contorno Dirichlet PML Parâmetros da discretização malha da discretização com tamanhos de 300 300 até 6900 6900 (tamanho máximo limitado pelo espaço de memória global da GPU usada, considerando precisão dupla). 1000 iterações no tempo Código sequencial compilado com as opções de otimização do gcc; a opção O3 deu os melhores tempos de processamento.
Tempo de processamento vs dimensão da malha Dirichlet PML 1x256 1x512 1x1024 1x256 1x512 1x1024 300 0.18 0.20 0.28 0.27 0.28 0.38 1500 3.7 3.7 4.0 4.8 4.9 5.1 2100 7.0 7.4 8.2 9.0 9.4 10.3 2700 11.8 11.6 12.2 15.3 15.1 15.7 3300 17.4 17.4 18.5 22.6 22.3 23.7 3900 23.8 23.8 24.7 30.4 30.7 31.9 4500 31.8 31.7 33.7 41.0 40.7 43.5 5100 41.4 40.7 42.0 53.7 53.6 56.5 5700 51.8 51.4 53.1 66.7 65.6 68.4 6300 63.8 63.4 66.3 80.8 80.6 85.2 6900 75.8 74.7 77.3 97.4 95.6 99.7
Aceleração Equações de Maxwell
Equac o es de Maxwell Implementac a o em CUDA Vaza o
Referências bibliográficas 1 D. D. Donno et al. GPU-based acceleration of computational electromagnetics codes. Int. Journal of Numerical Modelling: Electronic Networks, Devices and Fields, v. 26, n. 4, p. 309 323, 2013. 2 V. Kindratenko (editor), Numerical Computations with GPUs. Springer, 2014. 3 A. Taflove e S. Hagness, Computational electrodynamics: the finite-difference time-domain method. 2. ed. Boston: Artech House, 2000.
Referências bibliográficas 1 L. J. Veloso et al, Melhorando o desempenho computacional de um esquema de diferenças finitas para as equações de Maxwell. TEMA Trends in Applied and Computational Mathematics, v. 17, n. 1, p. 93 112, 2016. 2 K. Yee, Numerical solution of initial boundary value problems involving Maxwell s equations in isotropic media. IEEE Trans Antennas Propagation, IEEE, v. 62, n. 206, p. 302 307, 1966.