Grupo4 - FFT

De Física Computacional
Revisão de 21h25min de 29 de outubro de 2017 por Dfriggo (discussão | contribs)
Ir para navegação Ir para pesquisar

A Transformada rápida de Fourier (em inglês Fast Fourier Transform, ou FFT) é um algoritmo que torna viável o cálculo da Transformada Discreta de Fourier (DFT), que é a forma discretizada da [Transformada de Fourier]. A FFT permite transformar de forma rápida uma série de sinais discretos em uma amostra contendo as frequências desses sinais, desde que satisfaça algumas propriedades.


Transformada Discreta de Fourier

Em muitas aplicações se tem informação sobre um conjunto de dados, ao invés de uma função contínua. A Transformada Discreta de Fourier transforma esse conjunto de dados em um conjunto de tamanho igual com informação sobre as frequências da função que satisfaz o conjunto de dados.

Para um conjunto de dados igualmente espaçados, pode-se, ao considerar os dados como um período de uma função periódica, cujo período normalmente é considerado entre [π,π] para facilitar o cálculo (e que pode sempre ser transformada em uma função nesse interválo), mostrar que a transformada discreta de Fourier pode ser dada pela equação:

Fk=n=0N1fnei2πnk/N

A sua inversa é, em paralelo ao caso da transformada contínua,

fn=1Nn=0N1Fkei2πnk/N

A transformada também pode ser expressa em forma vetorial, como

A=𝐖𝐧𝐤a onde 𝐖𝐧𝐤 é definido como


𝐖𝐧𝐤=[e2πi00/Ne2πi01/Ne2πi0k/Ne2πi10/Ne2πi11/Ne2πi1k/Ne2πin0/Ne2πin1/Ne2πink/N]

O cálculo dessa expressão leva em torno de N2 passos para o resultado. Uma amostra com 3,000 pontos precisa de 9,000,000 operações para a transformada ser obtida, tornando a DFT inviável para aplicações rápidas.

Transformada Rápida de Fourier

É possível calcular a transformada com Nlog2N passos. Para isso se dispõe de um algoritmo chamado Transformada Rápida de Fourier. Considera-se um conjunto de pontos N=2p (com p inteiro, então, da definição da DFT

Fk=n=0N1fnei2πNkn

podemos dividir o somatório em 2:

Fk=n=0N/21f2nei2πNk2n+n=0N/21f2n+1ei2πNk(2n+1)

Fk=n=0N/21f2nei2πN/2kn+ei2πNkn=0N/21f2n+1ei2πN/2kn

Fk=n=0N/21f2nei2πN/2kn+C(k)n=0N/21f2n+1ei2πN/2kn

onde a soma em vermelho é a parte par e a soma em azul é a parte ímpar da transformada. As duas somas tem o mesmo expoente, que agora é dividido por N/2. Desse expoente, é evidente a relação entre o ponto k e o ponto k+N/2

ei2πN/2kn=ei2πN/2(k+N/2)n=ei2πN/2knei2πN/2N/2n=ei2πN/2kn1

Com essa relação, podemos ver que Fk e Fk+N/2 tem o mesmo expoente e podem ser calculadas ao mesmo tempo. Mais que isso, a nova forma da transformada pode ser sucessivamente dividida, cada vez produzindo somas com limites menores.


Exemplo

Suponha que temos a função sinusoidal a(t)=sin(2π1Hzt) e fazemos quatro medidas no intervalo de 1 segundo, resultando em

a0=0.00 a1=1.00 a2=0.00 a3=1.00

Com essas 4 medidas, podemos dividir a soma 2 vezes:

Ak=t=03atei2π4kt

Ak=t1=01a2t1ei2π2kt1+Ck1t1=01a2t1+1ei2π2kt1

Ak=t2=00a4t2ei2π1kt2+Ck2t2=00a4t2+2ei2π1kt2+Ck1t2=00a4t2+1ei2π1kt2+Ck3t2=00a4t2+3ei2π1kt2

e como temos Ckj=(ei2πNk)j podemos calcular

A0=1.00C011.00C03=0.00+i0.00

A1=1.00C111.00C13=0.00i2.00

A2=1.00C211.00C23=0.00+i0.00

A3=1.00C311.00C33=0.00+i2.00

FFT para N diferente de uma potência de 2

Mesmo com a FFT sendo um algoritmo extremamente eficiente para N=2p, esse dificilmente é o caso que encotramos. Ainda assim, para N altamente composto (N=r1r2...rm) o algoritmo ainda resulta em uma boa queda no tempo de cálculo.

Para o caso mais simples N=r1r2 a transformada pode ser escrita como

F(k1,k0)=n0=0r21[n1=0r11x(n1,n0)ei2πkn1r2]ei2πkn0

onde

k=k1r1+k0k0=0,1,...,r11k1=0,1,...,r21

n=n1r2+n0n0=0,1,...,r21n1=0,1,...,r11

assim a transformada que antes necessitava de N calculos, agora pode ser vista como r1+r2 calculos.

Algorítmo (usando recursão)

>>𝐟𝐮𝐧𝐜𝐭𝐢𝐨𝐧FFT(N,a)

>>>𝐢𝐟N=1𝐭𝐡𝐞𝐧

>>>returna;

>>>𝐞𝐥𝐬𝐞

>>>E=FFT(N/2,(a0,a2,...,aN2));

>>>O=FFT(N/2,(a1,a3,...,aN1));

>>>𝐟𝐨𝐫k=0tok<=N/21𝐝𝐨

>>>Ak=Ek+exp(i2πk/N)*Ok;

>>>Ak+N/2=Ekexp(i2πk/N)*Ok;

>>>returnA;

Implementação

A natureza recursiva do algoritmo da transformada rápida de fourier o torna ideal para implementações em linguagens funcionais como Haskell. Abaixo exibimos as partes mais relevantes do código, onde omitimos inclusões de bibliotecas e a definição das funções auxiliares evens e odds.

--esse termo multiplica o somatório de termos ímpares
f xs n = exp $ -(0:+2*pi)*n / genericLength xs

--caso a função seja chamada com apenas dois termos, temos o caso base
ffti [x,y] n = x + y * (exp $ -(0:+pi)*n)

--caso contrário aplique a função recursivamente separando o somatório em 
-- termos com índice par e com índice ímpar
ffti xs n = ffti (evens xs) n + f xs n * ffti (odds xs) n

--função que calcula os n coeficientes (ffti calcula um coeficiente)
fft xs [] = []
fft xs (y:ys) = (ffti xs y):(fft xs ys)

--exemplo
fft [0, 1, 4, 9] [0,1,2,3]

--saída ( :+ indica número complexo em Haskell)
[14.0 :+ 0.0, -4.0 :+ 8.0,  -6.0 :+ 0.0,  -4.0 :+ -8.0)]

Embora não seja uma linguagem puramente funcional Wolfram Mathematica também se presta a uma implementação direta e clara.

// caso base de uma lista contendo apenas dois termos
fft[{x_, y_}, n_] := x + y Exp[-I Pi n ]
// caso contrário, divida a lista entre termos com índice ímpar e par 
// e aplique a função recursivamente
fft[f_List, n_] :=                fft[Downsample[f, 2, 1], n] + 
    Exp[-((I 2 Pi n )/Length[f])] fft[Downsample[f, 2, 2], n]
//acima calcula-se com um coeficiente abaixo calcula-se todos
fft[f_List] := Table[fft[f, n] // N, {n, 0, Length[f] - 1}]

//exemplo
fft[{0, 1, 4, 9}]
{14., -4. + 8. I, -6., -4. - 8. I}

Exemplos

Abaixo encontra-se alguns exemplos básicos da transformada de fourier com base no código acima porém com modificações para lidar com o caso em que o intervalo de amostragem é diferente de [0,2π] e cuja taxa de amostragem é qualquer (diferente de 2πkN como assumido acima)

Gaussiana

A menos de uma normalização a função gaussiana é definida por: f(x)=e(x<x>)22σ2 Aplicando a transformada de fourier na curva gaussiana obtem-se outra gaussiana.

Observa-se que uma curva larga no espaço real corresponde a uma curva estreita no espaço de fourier e vice-versa. Esse é um fato matemático amplamente conhecido e se exprime também na física pelo Princípio da Incerteza de Heisenberg. Abaixo uma curva gaussiana mais larga que a anterior e sua transformada correspondentemente mais estreita.

Uma função par em relação à origem possui uma expansão em fourier com termos ímpares nulos, no entanto, deslocando a gaussiana um pouco para a direita e, portanto, quebrando sua simetria, vemos que a sua transformada possui uma parte complexa:

Oscilador Harmônico Amortecido

A curva que representa um oscilador harmônico amortecido é descrita por f(x)=sin(ax)ebx onde o termo senoidal, periódico, é amortecido pelo termo exponencial que leva a oscilação rapidamente a zero.

A transformada de fourier dessa curva possui parte real e imaginária, da parte imaginária dessa curva é possível obter a frequência de ressonância do fenômeno representado por ela. No caso abaixo vemos que a frequência de ressonância vale ±10Hz

Abaixo a parte real da transformada:

Aplicações

Equação de Schrödinger: propagação de onda de probabilidade

O cálculo da evolução temporal da equação de schrödinger é computacionalmente exigente. A cada passo de tempo é necessário recalcular a posição da onda de probabilidade que representa a partícula em cada ponto do domínio. Portanto, torna-se vantajoso o uso da transformada de fourier rápida. Além disso a própria transformada faz parte da solução, pois também deseja-se obter a sua evolução temporal no espaço de momento. O código foi desenvolvido por [https://jakevdp.github.io/blog/2012/09/05/quantum-python/ Jake Vanderplas, no entanto, sob extensas modificações foi possível entender o código e modifica-lo para representar situações diferentes das propostas pelo autor. Em seu site o autor explica a teoria por trás do problema e também como funciona seu algoritmo. A seguir exploramos a interação de uma onda de probabilidade com potenciais de diferentes formatos.

A parte principal do código modificado é exibidade abaixo:

Potencial Quadrado

Square.gif

Potencial Triangular

c:Arquivo:Triangular.gif

Potencial Batman

Batman.gif

Padrões de Difração