Швидкість конвергенції розв'язувача FFT Poisson


16

Який теоретичний коефіцієнт конвергенції для вирішувача FFT Poison?

Я розв'язую рівняння Пуассона: з n ( x , y , z ) = 3

2VН(х,у,z)=-4πн(х,у,z)
на домені[0,2]×[0,2]×[0,2]з періодичною граничною умовою. Ця щільність заряду є нейтральною. Розв’язок задається: VH(x)=n(
н(х,у,z)=3π((х-1)2+(у-1)2+(z-1)2-1)
[0,2]×[0,2]×[0,2] деx=(x,y,z). У зворотному просторі VH(G)=4πn(G)
VН(х)=н(у)|х-у|г3у
х=(х,у,z) деG- вектори зворотного простору. Мене цікавить енергія Хартрі: EH=1
VН(Г)=4πн(Г)Г2
Г У зворотному просторі це стає (після дискретизації): EH=2πG0 | n( G ) | 2
ЕН=12н(х)н(у)|х-у|г3хг3у=12VН(х)н(х)г3х
ТермінG=0опущений, що ефективно робить щільність заряду чистою нейтральною (а оскільки вона вже нейтральна, то все узгоджується).
ЕН=2πГ0|н(Г)|2Г2
Г=0

ЕН=12835π=1.16410 ...

Ось програма з використанням NumPy, яка робить розрахунок.

from numpy import empty, pi, meshgrid, linspace, sum
from numpy.fft import fftn, fftfreq
E_exact = 128/(35*pi)
print "Hartree Energy (exact):      %.15f" % E_exact
f = open("conv.txt", "w")
for N in range(3, 384, 10):
    print "N =", N
    L = 2.
    x1d = linspace(0, L, N)
    x, y, z = meshgrid(x1d, x1d, x1d)

    nr = 3 * ((x-1)**2 + (y-1)**2 + (z-1)**2 - 1) / pi
    ng = fftn(nr) / N**3

    G1d = N * fftfreq(N) * 2*pi/L
    kx, ky, kz = meshgrid(G1d, G1d, G1d)
    G2 = kx**2+ky**2+kz**2
    G2[0, 0, 0] = 1  # omit the G=0 term

    tmp = 2*pi*abs(ng)**2 / G2
    tmp[0, 0, 0] = 0  # omit the G=0 term
    E = sum(tmp) * L**3
    print "Hartree Energy (calculated): %.15f" % E
    f.write("%d %.15f\n" % (N, E))
f.close()

А ось графік конвергенції (просто побудуйте графік conv.txtз вищевказаного сценарію, ось ноутбук, який робить це, якщо ви хочете грати з цим самостійно):

Графік конвергенції FFT

Як бачите, конвергенція лінійна, що було для мене несподіванкою, я думав, що FFT конвергується набагато швидше, ніж це.

Оновлення :

Рішення має зусилля на кордоні (я цього раніше не усвідомлював). Для того щоб FFT швидко конвергувався, рішення повинно мати всі похідні гладкими. Тому я також спробував наступну праву частину:

nr = 3*pi*sin(pi*x)*sin(pi*y)*sin(pi*z)/4

VН=гріх(πх)гріх(πу)гріх(πz)ЕН=3π8

Хтось знає якийсь тест у 3D, щоб я міг бачити швидше конвергенцію, ніж лінійний?


Ондрей, чи не перетворення Фур'є вашої гладкої щільності є дельта-функцією? Зізнаюся, я лінувався запускати це, але слід отримати точну відповідь з першої спроби.
Метт Кнеплі

Я думаю це. Але це не збігається за одну ітерацію, як видно із сюжетів ноутбука. Я поняття не маю, що відбувається.
Ondřej Čertík

Ондрей, ти впевнений, що реалізація правильна? Я пам’ятаю, як намагався реалізувати спектральні розв'язувачі для виконання домашніх завдань у середній школі та повністю махав постійними. Я помічаю, що ви вимірюєте помилку, дивлячись на абсолютну відстань між обчисленою та точною енергією. Як виглядає ваша конвергенція щодо фактичного вирішення проблеми? Це має бути легко обчислити і навіть скласти графік над двовимірним фрагментом проблеми.
Арон Ахмадія

Арон --- Я перевірив свою реалізацію на якомусь іншому коді, але перевіряв його на неправильну початкову вибірку, тому в обох кодах була однакова помилка. Метт мав рацію, тепер він сходиться з першої спроби. Дивіться мою відповідь нижче.
Ondřej Čertík

Відповіді:


10

Дозвольте спочатку відповісти на всі питання:

Який теоретичний коефіцієнт конвергенції для вирішувача FFT Poison?

Теоретична конвергенція експоненціальна до тих пір, поки рішення буде досить гладким.

Наскільки швидко ця енергія повинна сходитися?

Енергія Хартрі ЕНповинні сходитися експоненціально для досить гладкого рішення. Якщо розчин менш гладкий, то конвергенція повільніше.

Хтось знає якийсь тест у 3D, щоб я міг бачити швидше конвергенцію, ніж лінійний?

Будь-яка права сторона, яка виробляє рішення, яке є періодичним і нескінченно диференційованим (у тому числі через межу періодичного періоду), має сходитися експоненціально.


У наведеному вище коді трапляється помилка, яка призводить до того, що конвергенція буде повільнішою, ніж експоненціальна. Використовуючи код гладкої щільності ( https://gist.github.com/certik/5549650/ ), наступний патч виправляє помилку:

@@ -6,7 +6,7 @@ f = open("conv.txt", "w")
 for N in range(3, 180, 10):
     print "N =", N
     L = 2.
-    x1d = linspace(0, L, N)
+    x1d = linspace(0, L, N+1)[:-1]
     x, y, z = meshgrid(x1d, x1d, x1d)

     nr = 3*pi*sin(pi*x)*sin(pi*y)*sin(pi*z)/4

Проблема полягала в тому, що вибірка реального простору не може повторити першу та останню точку (яка має однакове значення через періодичну граничну умову). Іншими словами, проблема полягала у створенні початкової вибірки.

Після цього виправлення щільність конвергується за одну ітерацію, як сказав Метт вище. Тому я навіть не побудував графіки конвергенції.

Однак можна спробувати більш складну щільність, наприклад:

     nr = 3*pi*exp(sin(pi*x)*sin(pi*y)*sin(pi*z))/4

то конвергенція експоненціальна, як і очікувалося. Ось графіки збіжності для цієї щільності: введіть тут опис зображення введіть тут опис зображення


Дивовижно. Вибачте, що мені більше не допомогло!
Арон Ахмадія
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.