Reihenfolge der MATLAB FFT-Frequenzen

9

Dieses Wikibook gibt an, dass die Ausgabe von FFTMATLABs den Wellenzahlen entspricht, die wie folgt bestellt sind:

k={0,1,...,n2,n2+1,n2+2,...,1}

In den Beispielcodes auf derselben Seite sind die Wellenzahlen jedoch als codiert

k = [0:n/2-1 0 -n/2+1:-1];

Dies ist das gleiche wie beim ersten Mal, jedoch wird die Wellenzahl (die "maximale Wellenzahl") durch . Es scheint seltsam, dass sie zweimal würden .0 0n/200

Es scheint, dass die richtige Reihenfolge erforderlich ist, um Ableitungen über Fourier-Transformationen zu erhalten, wie im Wikibook beschrieben. Welche davon ist richtig und dokumentiert MATLAB dies irgendwo?

Zweifel
quelle
3
schau in die Funktion fftshift. Es nimmt die Ausgabe von fft und ordnet sie von [-n / 2 + 1: n / 2-1] neu an, was bei Ihrer Verwirrung helfen sollte.
Godric Seer
Ist das nicht etwas, das Sie schnell selbst testen können? Mit ein paar Experimenten kann man leicht herausfinden, in welcher Reihenfolge die Ausgabe von FFT ist.
Federico Poloni

Antworten:

4

Ich möchte meinen Kommentar erweitern und das Beispiel, auf das Sie verweisen, auf eine Weise überarbeiten, die verständlicher sein sollte als das Original, und erklären, warum fftdie Koeffizienten so zurückgegeben werden, wie sie es tun.

Als Referenz lautet der fft-Teil des Beispiels:

Nx = size(x,2);
k = 2*pi/(b-a)*[0:Nx/2-1 0 -Nx/2+1:-1];
dFdx = ifft(1i*k.*fft(f));
d2Fdx2 = ifft(-k.^2.*fft(f));

Ich habe einen weiteren Codeabschnitt direkt darunter hinzugefügt:

Nx = size(x,2);
k = 2*pi/(b-a)*(-Nx/2:Nx/2-1);
dFdxp = ifft(ifftshift(1i*k.*fftshift(fft(f))));
d2Fdx2p = ifft(ifftshift(-k.^2.*fftshift(fft(f))));

und wickelte beide Codeteile in ein tic; tocfür die richtige Zeit. In einem besser lesbaren Format verwendet die zweite Methode:

ckf = fftshift(fft(f));
ckdf = 1i*k.*ckf;
df = ifft(ifftshift(ckdf));

Der erste Unterschied ist, dass das zweite Beispiel viel intuitiver ist k. Dies ist der Hauptvorteil des zweiten Beispiels, da k jetzt in der Form vorliegt, in der wir über sie nachdenken. In der zweiten und dritten Zeile musste ich fftshiftum den Anruf herum hinzufügen fft, dann einen Anruf ifftshiftdirekt innerhalb des Anrufs an ifft. Diese zusätzlichen Funktionsaufrufe ordnen die Koeffizienten von dem, was der Computer benötigt, um mit ihnen zu arbeiten, zu der Art und Weise neu, wie Menschen normalerweise über sie denken.

Das Problem mit dem zweiten Beispiel ist, dass dies zwar kfür uns intuitiver ist, die internen Matrizen jedoch zum Lösen und Invertieren fftin nicht so vorteilhaften Formen verbleiben. Entweder müssen wir die Reihenfolge mit Aufrufen auf fftswitchändern ifftswitchoder es muss fest in die fftFunktionen codiert werden . Dies ist weniger fehleranfällig für Benutzer (vorausgesetzt, sie sind mit der Funktionsweise von fft nicht vertraut, wie es viele Leute tun), aber Sie zahlen einen Preis in der Laufzeit.

Wie ich bereits sagte, fügte ich zum Vergleich Timing-Aufrufe um die beiden Blöcke hinzu und lief für mehrere N. Die Timing-Ergebnisse waren:

N =     1000,  Ex1 = 0.000222 s,   Ex2 = 0.007072 s
N =    10000,  Ex1 = 0.001576 s,   Ex2 = 0.003506 s
N =   100000,  Ex1 = 0.023857 s,   Ex2 = 0.034051 s
N =  1000000,  Ex1 = 0.213816 s,   Ex2 = 0.406250 s
N = 10000000,  Ex1 = 4.555143 s,   Ex2 = 7.102348 s

Wie Sie sehen können, verlangsamt das Hin- und Herwechseln der Werte den Prozess erheblich, insbesondere bei niedrigem N (wo es 30x langsamer ist). Dies ist nur ein Beispiel, und Ihr Computer zeigt möglicherweise leicht unterschiedliche Trends, abhängig von der Speichergeschwindigkeit, den Prozessorkernen / -geschwindigkeiten usw., aber dies veranschaulicht den Punkt. Der Grund für fftdie verwirrende Ausgabe liegt darin, dass Sie einen nicht trivialen Bruchteil Ihrer Rechenzeit sparen.

Godric Seer
quelle
3
Dies beantwortet immer noch nicht die ursprüngliche Frage - warum funktioniert es überhaupt, zweimal Null einzuschließen? Und warum schlägt die Dokumentation vor, dass Null nur einmal enthalten sein sollte?
David Ketcheson
2

Ihre Frage bezüglich des Ersatzes der Wellenzahl ist ziemlich schwierig. Im Allgemeinen soll eine solche Wellenzahlmodifikation nicht Flops retten, wie einige hier vorgeschlagen haben, sondern die analytischen Besonderheiten beispielsweise bestimmter Differentialoperatoren berücksichtigen. Ich bin sehr überrascht, dass ich in Trefethens Spektralmethoden keine verwandte Diskussion finden konnte. Um fortzufahren, gehe ich davon aus, dass Sie sich Sorgen über die FFT-basierte spektrale Differenzierung machen und Transformationen in einem Bereich mit gleichmäßiger Kardinalität durchführen.

Die Faustregel für ungerade Ableitungen lautet: Setzen

k = [0:n/2-1 0 -n/2+1:-1];

und für gerade Derivate zu setzen

k = [0:n/2 -n/2+1:-1];

Wenn Sie mit Polstern zu tun haben, ist die Behandlung der Nyquist-Frequenz ähnlich langwierig. Es gibt eine ausgezeichnete Zusammenfassung, die diese Themen hier beweist und kommentiert !

Stuart Hilton
quelle
0

NN/2xRN/2N/2N/2

mu7z
quelle