Translate

piątek, 15 kwietnia 2011

18. Energia stanu podstawowego kationu cząsteczki wodoru z wykorzystaniem metody Monte Carlo i algorytmu Metropolisa

Przygotowany uprzednio program do obliczania energii stanu podstawowego atomu wodoru z wykorzystaniem metody Monte Carlo i algorytmu Metropolisa zaadaptowałem do obliczenia energii stanu podstawowego cząsteczki H2+. Funkcja falowa, którą wybrałem do obliczeń była kombinacją liniową orbitali 1s atomów wodoru 1:
Parametrem obliczeniowym - odległość między protonami Rj w układzie. Rysunek poniżej przedstawia sytuację geometryczną użytą do obliczeń:
W wyniku przeprowadzonych obliczeń otrzymałem zbiór danych, które są przedstawione na poniższym wykresie:
Wartość minimalna energii wynosi około -0.567 j.at. przy odległości między protonami wynoszącej 2.5 angstrema.
Tekst programu, który wygenerował zbiór wyników jest przytoczony poniżej:
DECLARE FUNCTION fufal! (x!, y!, z!)
DECLARE FUNCTION GRNF! ()  'gaussowski generator pseudolosowy
                           'jednostki atomowe
llos = 500000            'liczba losowan
h = .01                  'krok rozniczkowania
h2 = h * h               'kwadrat kroku rozniczkowania
DIM SHARED Rj            'odl. miedzy protonami
OPEN "H2plus.txt" FOR APPEND AS #1
FOR Rj = .9 TO 6 STEP .1    'obl. energi w zal. od Rj

En = 0                   'zerowanie energii do sumowania
x = 0: y = 1.2: z = 0    'poczatkowy punkt lancucha Markowa
FOR i = 1 TO llos
  xzapas = x             'zabezpieczenie starych wspolrzednych
  yzapas = y
  zzapas = z

  psi = fufal(x, y, z)    'wartosc psi w punkcie (x,y,z)
  psikw = psi * psi       'kwadrat psi

           'Losowanie nowego punktu  (xn,yn,zn)
  xn = 2 * RND - 1        'zakres (-1, 1)
  yn = 2 * RND - 1
  zn = 2 * RND - 1

  pr = SQR(xn*xn + yn*yn + zn*zn)  'promien punktu (xn,yn,zn)
  skok = .6 * GRNF         'skok przypadkowy wg rozkladu Gaussa

  x = x + xn * skok / pr  'poprawione wspolrzedne nowego punktu
  y = y + yn * skok / pr
  z = z + zn * skok / pr
 
  psinowa = fufal(x, y, z)     'wartsc psi w nowym punkcie
  psinowakw = psinowa * psinowa

'obliczanie warunku przejscia lancucha do nowego punktu

 rel = psinowakw / psikw   'stosunek nowej i starej psi
  IF rel < 1 THEN          'przejscie bezwarunkowe gdy rel >= 1
    IF RND > rel THEN      'przejscie odrzucone
      x = xzapas
      y = yzapas
      z = zzapas
      psinowa = fufal(x, y, z)
    END IF
 END IF

 'obliczanie calki z energii lokalnych
  'obliczanie pochodnej w punkcie (x,y,z)
  fufal2 = 2 * fufal(x, y, z)
  d1 = (fufal(x - h, y, z) - fufal2 + fufal(x + h, y, z)) / h2
  d2 = (fufal(x, y - h, z) - fufal2 + fufal(x, y + h, z)) / h2
  d3 = (fufal(x, y, z - h) - fufal2 + fufal(x, y, z + h)) / h2
 
  Lappsi = -(d1 + d2 + d3) / 2'druga poch. psi w punkcie (x,y,z)

  V1 = -1/(SQR((x - Rj/2)^2 + y*y + z*z))'potencjal  psi/psi=1
  V2 = -1/(SQR((x + Rj/2)^2 + y*y + z*z))
  En = En + Lappsi/psinowa+V1+V2+1/Rj    'suma energii lok.
 NEXT i

   PRINT #1, Rj, En / llos   'druk zm. wariacyjnej i en. calk.
NEXT Rj
  CLOSE #1
END

FUNCTION fufal (x, y, z)
  x1 = x - Rj / 2
  x2 = x + Rj / 2
  r1 = SQR(x1 * x1 + y * y + z * z)
  r2 = SQR(x2 * x2 + y * y + z * z)
  fufal = EXP(-r1) + EXP(-r2)
END FUNCTION

FUNCTION GRNF
  r1 = SQR(-LOG(1 - RND))
  GRNF = r1 * SIN(2 * 3.14159265# * RND)
END FUNCTION


czwartek, 7 kwietnia 2011

17. Dystrybucja zmiennej x dla kwadratu funkcji logarytmicznej w obszarze zachowania chaotycznego

W poprzednim poście pokazałem, że kwadrat funkcji logarytmicznej posiada wykładnik Lapunowa o wartościach powyżej zera. Poniżej przedstawiam wynik działania programu, który liczy dystrybucję zmiennej x w obszarze chaotycznym:
'Dystrybucja x dla kwadratu funkcji logarytmicznej
CLS : SCREEN 12
vec = 510    'rozmiar wektora zbierana danych
DIM d(vec)
x = .7
llos = 10000  'liczba iteracji
c = 1.2       'dla c=1.2 min=1.15E-9, max=507.92
OPEN "dystryb.txt" FOR APPEND AS #1
FOR i = 1 TO llos
  x = c * LOG(x) ^ 2  'funkcja logarytmiczna
  yd = INT(x)         'wskaznik w wektorze
  d(yd) = d(yd) + 1
NEXT i

FOR i = 1 TO vec
   PRINT #1, i, d(i)      'drukowanie wynikow
  'PSET (i, 400 - d(i))
NEXT i
CLOSE #1
Wynikiem działania programu jest zbiór danych, które przedstawiłem na poniższym wykresie:
Bez szczegółowej analizy można powiedzieć, że dystrybucja przypomina przebiegiem funkcję 1/x.

16. Wykładnik Lapunowa dla kwadratu funkcji logarytmicznej

Zaobserwowałem, że funkcja logarytmiczna może zachowywać się chaotycznie. W celu potwierdzenia takiej możliwości obliczyłem wykładniki Lapunowa dla szeregu wartości stałej c w równaniu 1:
Zadanie to realizuje program przedstawiony poniżej:
'wykladnik Lapunowa
'dla rownania logarytmicznego
CLS : SCREEN 12
N = 4000      ' liczba iteracji
OPEN "lapunow3.txt" FOR APPEND AS #1
FOR c = 1.1 TO 3 STEP .01    'wspolcz. w rown. logarytmicznym
  suma = 0
  x = .7
  FOR i = 1 TO N
    suma = suma + LOG(ABS(2 * c * LOG(x) / x))'suma log pochod.
    x = c * LOG(x) ^ 2 'iterowane rown. logarytmiczne
  NEXT i
  Lapunow = suma / N    ' wstpoczynnik Lapunowa
  PRINT #1, c, Lapunow
  'PSET (c * 150, 100 - Lapunow * 100)  'obraz na ekranie
NEXT c
CLOSE #1
Program generuje zbiór wartości, które są przedstawione na poniższym wykresie. Należy dodać, że wykres został skompilowany z dwóch zbiorów dla c (0.1,1.0) oraz (1.1, 3.0). Podzial był związany z błedami zaokrągleń zmiennej c. Zaokrąglenia powodowały, że pojawiły się błędy dla dla wartości c około 1.58.
Wykres pokazuje, że chaotyczne zachowanie kwadratu logarytmu jest możliwe dla c w obszarze od około 0.10 do około 1.84.

środa, 6 kwietnia 2011

15. Dystrybucja zmiennej równania logistycznego dla obszaru chaotycznego

Przedmiotem tego wpisu jest chaotyczne zachowanie się równania logistycznego dla pewnych wartości stałej c danego wzorem 1:
Zadałem sobie pytanie, ile razy wybierana jest konkretna wartość xi podczas procesu iteracji równania 1. Zagadnienie to rozwiązałem przy użyciu programu, który zlicza pojawiające się wartości zmiennej x a wynik zliczania wpisuje do wektora d. W celu "rozciągnięcia" zakresu zmiennych każda wartość xi jest mnożona przez 10000. Tekst programu przedstawiłem poniżej:
'dystrybucja zm. x funkcji logistycznej
DIM d(10000)
y = .7
llos = 1000000
c = 3.8
OPEN "dystryb.txt" FOR APPEND AS #1
FOR i = 1 TO llos
  x = y
  y = c * x * (1 - x)
  yd = INT(y * 10000)
  d(yd) = d(yd) + 1
NEXT i

FOR i = 1 TO 10000
  PRINT #1, i, d(i)
NEXT i
CLOSE #1

Wynikiem działania programu jest zbiór danych, ktore zamieszczone są poniżej:
Można zauważyć, że średnio rzecz biorąc, najliczniej prezentowana wartość około 250. Liczności wzrastają na brzegach przedziału. Wspomnę, że zastosowałem pojedynczą precyzję w deklaracjach zmiennych. Zasadniczo powinienem użyć definicji zmiennych w podwójnej precyzji. Ten zabieg powinien spowodować "wygładzenie" poszarpanego wykresu dystrybucji.

14. Wykładnik Lapunowa dla rownania logistycznego. Wprawka I

Wykładnik Lapunowa jest dla mnie interesujący z tego względu, że pozwala określić wartości współczynników w równaniach, które mogą zachowywać się w sposób chaotyczny. Chcąc stwierdzić, czy dobrze rozumiem istotę zagadnienia napisałem program w języku BASIC, który liczy wykładniki Lapunowa dla równania logistycznego postaci 1:
Wykładnik Lapunowa określony jest wzorem 2:
przy czym każdą następną wartość x oblicza się ze wzoru 1.
Tekst programu znajduje się poniżej. Program umożliwia zapisanie danych na dysku lub obejrzenie wyniku w postaci wykresu bezpośrednio na ekranie:
'wykladnik Lapunowa
'dla rownania logistycznego
SCREEN 12
N = 4000      ' liczba iteracji
x = .7        ' punkt poczatkowy
CLS : SCREEN 12
OPEN "lapunow.txt" FOR APPEND AS #1
FOR c = 2.1 TO 3.9 STEP .001  'wspolcz. w rown. logistycznym
  suma = 0
  FOR i = 1 TO N
    suma = suma + LOG(ABS(c - 2 * c * x)) 'suma log pochodnych
    x = c * x * (1 - x)  'iterowane rown. logistyczne
  NEXT i
  Lapunow = suma / N     'wykladnik Lapunowa
  PRINT #1, c, Lapunow
  'PSET (c * 150 - 200, 200 - Lapunow * 100) 'obraz na ekranie
NEXT c
CLOSE

Wynik działania programu znajduje się poniżej w postaci wykresu:
Dla wartości wykładnika Lapunowa >0 równanie zachowuje się chaotycznie.

środa, 16 marca 2011

11-13.Energia stanu podstawowego atomu wodoru z wykorzystaniem pojęcia energii lokalnej i funkcji gęstości radialnej (połaczone 02.2020 r.)

Wzór wyrażający wartość średnią energii dla znormalizowanych i rzeczywistych funkcji falowych ma postać 1.
Dla układów o symetrii kulistej element dv może być wyrażony, jako różniczka 2 wzoru określającego objętość kuli
Po wstawieniu 2 do 1, pomnożeniu prawej strony przez stosunek
i uporządkowaniu wyrazów otrzymujemy wzór 3 na całkowitą, średnią energię układu. Wzór zawiera tzw. „energię lokalną”
oraz fragment będący wyrażeniem na funkcję gęstości radialnej.
Po przejściu od całkowania do sumowania otrzymujemy wzór 4 na przybliżoną wartość energii układu wyrażoną przez (radialną) gęstość elektronową, energię lokalną i liczbę punktów n w przestrzeni wokółjądrowej, w których dokonujemy obliczeń a następnie sumowania.
Z drugiej strony do obliczenia energii z wykorzystaniem metody Monte Carlo i algorytmu Metropolisa stosuje się wzór 5.
Sugerujemy, że wzory 4 i 5 są równoważne w tym sensie, że algorytm Metropolisa z wykorzystaniem wartości stosunku „nowej” i „starej” wartości funkcji gęstości elektronowej
jako kryterium wyboru przejścia do nowego punktu, faworyzuje pewne wartości promienia r, w których oblicza się energie lokalne. Innymi słowy, pewna wartość promienia może być wykorzystywana wielokrotnie do obliczenia gęstości a następnie wartości energii lokalnej. Zjawiska tego nie widać explicite we wzorze 5. W celu rozpoznania tego zagadnienia, rozpatrzmy model atom wodoru w przybliżeniu Borna-Oppenheimera i nieskończenie ciężkiego jądra. Stacjonarne równanie Schroedingera przyjmuje w jednostkach atomowych postać 6:
Wybieramy funkcję próbną postaci
Dla wybranego modelu metoda Monte Carlo i algorytm Metropolisa generują zbiór wartości promieni r (program liczno.bas) o charakterystyce przedstawionej na Rys. 1. dla 500000 losowań i dla c = 1.0.
'Program liczno.bas
DECLARE FUNCTION fufal! (x!, y!, z!)
DECLARE FUNCTION GRNF! ()  'gaussowski generator pseudolosowy
                           'jednostki atomowe
CLS
llos = 500000            'liczba losowan
DIM SHARED c             'globalna zmienna wariacyjna
DIM x(800)               'wektor licznosci promieni
c = 1!                   'wybrana wartosc zm. wariacyjnej
OPEN "dane.DAT" FOR APPEND AS #1

x = 0: y = 1.2: z = 0    'punkt startowy
FOR i = 1 TO llos
  xzapas = x             'zabezpieczenie starych wspolrzednych
  yzapas = y
  zzapas = z

  psi = fufal(x, y, z)    'wartosc psi w punkcie (x,y,z)
  psikw = psi * psi       'kwadrat psi

           'Losowanie nowego punktu  (xn,yn,zn)
  xn = 2 * RND - 1        'zakres (-1, 1)
  yn = 2 * RND - 1
  zn = 2 * RND - 1

  pr = SQR(xn*xn + yn*yn + zn*zn)  'promien punktu (xn,yn,zn)
  skok = .6 * GRNF         'skok przypadkowy wg rozkladu Gaussa

  x = x + xn * skok / pr  'poprawione wspolrzedne nowego punktu
  y = y + yn * skok / pr
  z = z + zn * skok / pr
 
  psinowa = fufal(x, y, z)     'wartsc psi w nowym punkcie
  psinowakw = psinowa * psinowa

'obliczanie warunku przejscia lancucha do nowego punktu

 rel = psinowakw / psikw   'stosunek nowej i starej psi
  IF rel < 1 THEN          'przejscie bezwarunkowe gdy rel >= 1
    IF RND > rel THEN      'przejscie odrzucone
      x = xzapas           'przywrocenie starych wartosci
      y = yzapas
      z = zzapas
      psinowa = fufal(x, y, z)
    END IF
 END IF

  rn = SQR(x * x + y * y + z * z) 'promien do zliczania
  liczba = INT(rn * 100)     ' definicja adresu wektora promieni
  x(liczba) = x(liczba) + 1  ' zliczanie promieni
 NEXT i

FOR i = 1 TO 620
  PRINT #1, i / 100, x(i)
NEXT i
CLOSE
END

FUNCTION fufal (x, y, z)
  r = SQR(x * x + y * y + z * z)
  fufal = EXP(-c * r)
END FUNCTION

FUNCTION GRNF
  r1 = SQR(-LOG(1 - RND))
  GRNF = r1 * SIN(2 * 3.14159265# * RND)
END FUNCTION

Graficzna prezentacja wyniku działania programu


Wykres ten ilustruje anonsowany wyżej fakt, że energie lokalne obliczone dla danej wartości r są sumowane tyle razy, ile razy dany promień został wybrany podczas błądzenia. Aproksymacja przedstawionego zbioru punktów za pomocą funkcji opartej na funkcji gęstości radialnej daje wzór postaci 7.
Otrzymana zależność 7 zgadza się, co do postaci, ze wzorem określającym funkcję gęstości radialnej z wyjątkiem wartości przedwykładniczego współczynnika liczbowego. Liczba 20000 znacznie przekracza oczekiwaną teoretycznie wielkość 4*pi. Ten wynik można zinterpretować, jako koszt obliczeniowy poniesiony w związku z zastosowaniem metody Monte Carlo i błądzenia wedle algorytmu Metropolisa, gdyż dokładność obliczenia energii całkowitej układu wzrasta wraz ze wzrostem liczby kroków błądzenia.
Na podstawie uzyskanych wyników proponujemy wykorzystać wzór 4 do obliczania energii układu. Oznacza to, że w obliczeniach energii całkowitej układów kwantowych z wykorzystaniem energii lokalnych oraz metody Monte Carlo i funkcji gęstości radialnej, stosowanie algorytmu Metropolisa (błądzenia pseudoprzypadkowego) nie jest konieczne. Dodatkowo, w przypadkach uzasadnionych kosztem obliczeń i symetrią układu, metodę Monte Carlo (losowanie punktów) można zastąpić systematycznym wyborem punktów, w których oblicza się energię lokalną a następnie całkowitą energię badanego układu. Zagadnienie to będzie przedmiotem następnej pracy.

W celu obliczenia tytułowej energii wykorzystamy uprzednio wyprowadzony wzór postaci 1 zawierający energię lokalną i funkcję gęstości radialnej:
dla funkcji exp(-cr). Zastosowana metoda nie wykorzystuje algorytmu Metropolisa. Przedmiotem losowania (metoda Monte Carlo) będą wartości promienia wodzącego r elektronu w zakresie od zera do rmax. Sprawdzimy wyniki obliczeń dla zbioru wartości zmiennej wariacyjnej c i określimy jakość obliczenia energii dla różnych liczb przeprowadzonych losowań. Omawiane zagadnienia realizuje program MCnoMet.bas

'program liczy energię ale bez algorytmu Metropolisa
'jednostki atomowe
DECLARE FUNCTION fufal! (r!)

DIM SHARED c 'zmienna globalna
pi = 3.1415  'ludolfina
llos = 5000  'liczba losowan promienia
rmax = 5     'maksymalna dlugosc promienia 
OPEN "energie.dat" FOR APPEND AS #1
CLS
SCREEN 12
FOR c = .1 TO 2 STEP .1    'obl. energii jako funkcja zm. war. c
  Energia = 0
  suma = 0
  FOR i = 1 TO llos
    r = RND * rmax
    ro = fufal(r) * fufal(r)        'gestosc elektronowa
    roradial = 4 * pi * r * r*ro    'funkcja gestosci radialnej
        'Hpsi/psi*roradial
    Elokalna = (-c * c / 2 + (c - 1) / r) * roradial   
    Energia = Energia + Elokalna
    suma = suma + roradial
  NEXT i
     PRINT #1, c, Energia / suma
NEXT c
CLOSE

FUNCTION fufal (r)
  fufal = EXP(-c * r)
END FUNCTION
Rys. 1 przedstawia wyniki działania programu dla 5000 losowań

Tabela 1. przedstawia wartość liczbową energii minimalnej i wartości zmiennej wariacyjnej c w zależności od liczby losowań (llos).


llos             c              Energia
10              1.1             -0.5174
100             1.0             -0.5000001
500             1.0             -0.4999999
1000            1.0             -0.5000001
2000            1.0             -0.5000001
5000            1.0             -0.5000000
7000            1.0             -0.4999999
Wyniki pokazują, że już sto losowań wartości promienia daje dokładną wartość energii (do obliczeń użyliśmy zmiennych pojedynczej precyzji) dla prawidłowej wartości zmiennej wariacyjnej c = 1.

W celu obliczenia tytułowej energii wykorzystamy uprzednio wyprowadzony wzór postaci 1 zawierający energię lokalną i funkcję gęstości radialnej:
dla funkcji exp(-cr). Zastosowana tu metoda nie wykorzystuje algorytmu Metropolisa i rezygnuje metody Monte Carlo na korzyść systematycznego wzrostu wartości promienia wodzącego r elektronu w zakresie od rmin do rmax. Sprawdzimy wyniki obliczeń dla zbioru wartości zmiennej wariacyjnej c. Omawiane zagadnienia realizuje program noMCnoMe.bas:

'Author Wojciech Szczepankiewicz
'Silesian University of Technology
'Gliwice, Poland

DECLARE FUNCTION fufal! (r!)
'atomic units
DIM SHARED c 'variational variable
pi = 3.1415  'ludolphine
rmin = .01   'min radius
rmax = 5     'max radius
OPEN "data.dat" FOR APPEND AS #1
CLS
'energy calc. as a function of variational variable
FOR c = .1 TO 2 STEP .05
  Energy = 0
  sum = 0
  FOR r = rmin TO rmax STEP .01
    rhoradial = fufal(r) * fufal(r)     'density
    freq = 4 * pi * r * r * rhoradial   'radial density function
        'Hpsi/psi*rhoradial
    Elocal = (-c * c / 2 + (c - 1) / r) * freq
    Energy = Energy + Elocal
    sum = sum + freq
   NEXT r
     PRINT #1, c, Energy / sum
NEXT c
CLOSE

FUNCTION fufal (r)
  fufal = EXP(-c * r)
END FUNCTION
Rys. 1 przedstawia wyniki działania programu dla kolejnych 499 punktów promienia
W podsumowaniu należy stwierdzić, że dla trywialnego zagadnienia, jakim jest model atomu wodoru, zastosowanie wzoru 1 pozwala zmniejszyć znacznie koszt obliczeń w porównaniu do algorytmu Metropolisa. Otwartym pozostaje pytanie, czy ta korzyść występuje również w wypadku zagadnień nietrywialnych.

poniedziałek, 28 lutego 2011

5. Energia stanu podstawowego atomu wodoru według metody Monte Carlo. Połączone wprawki II-VII - Aktualizacja 01.2020.

Poprzednia wprawka pozwoliła mi zrozumieć istotę metody Monte Carlo. Teraz postanowiłem zastosować ją do szkolnego, ale nieco bardziej zaawansowanego zagadnienia. Stany energetyczne atomu wodoru można obliczyć z wykorzystaniem wzorów Bohra lub równania Schroedingera. Tu zastosowałem metoda Monte Carlo, która jest popularnym w fizyce i chemii sposobem obliczania stanów rozmaitych układów kwantowych. W celu obliczenia stanu podstawowego atomu wodoru wykorzystałem algorytm opublikowany przez prof. A. Dawida (obecnie Wyższa Szkoła Biznesu w Dąbrowie Górniczej). Sporo czasu zajęło mi rozpracowanie oryginalnego algorytmu i zrozumienie działania jego składowych. Po kosmetycznych zmianach kodu zapisałem go w języku VBA dla Excela. Poniżej zapisany program oblicza zależność energii stanu podstawowego atomu wodoru od wartości zmiennej wariacyjnej. Minimalna wartość energii dla obliczenia ścisłego wynosi -0.5 hartree.

Public c, pi As Double
Sub atomH() 'procedura oblicza energię stanu podstawowego atomu wodoru
Dim x, y, z, h, h2 As Double
pi = 3.14159265
llos = 1000000            'liczba losowań
h = 0.01                 'krok różniczkowania
h2 = h * h               'kwadrat kroku różniczkowania
j = 1                    'licznik rzędu w tablicy Excela
For c = 0.2 To 1.9 Step 0.1 'obl. energii w zal. od zm. wariacyjnej
  En = 0                   'zerowanie energii do sumowania
  x = 0: y = 1.2: z = 0    'punkt początkowy
    For i = 1 To llos      'pętla obliczeniowa
    xzapas = x             'zabezpieczenie starych współrzędnych
    yzapas = y
    zzapas = z

    psi = fufal(x, y, z)    'wartość psi w punkcie (x,y,z)
    psikw = psi * psi       'kwadrat psi

           'Losowanie nowego punktu  (xn,yn,zn)
    xn = 2 * Rnd - 1        'zakres (-1, 1)
    yn = 2 * Rnd - 1
    zn = 2 * Rnd - 1

    pr = Sqr(xn * xn + yn * yn + zn * zn)  'promień punktu (xn,yn,zn)
    skok = 0.6 * GRNF        'skok przypadkowy wg rozkładu Gaussa

    x = x + xn * skok / pr  'poprawione współrzędne nowego punktu
    y = y + yn * skok / pr
    z = z + zn * skok / pr
 
    psinowa = fufal(x, y, z)     'wartość psi w nowym punkcie
    psinowakw = psinowa * psinowa

'obliczanie warunku przejścia łańcucha do nowego punktu

   rel = psinowakw / psikw   'stosunek nowej i starej psi
    If rel < 1 Then          'przejście bezwarunkowe gdy rel >= 1
      If Rnd > rel Then      'przejście odrzucone
        x = xzapas
        y = yzapas
        z = zzapas
        psinowa = fufal(x, y, z)
      End If
   End If

 'obliczanie sumy energii lokalnych
 'obliczanie drugich pochodnych cząstkowych w punkcie (x,y,z)
  fufal2 = 2 * fufal(x, y, z)
  d1 = (fufal(x - h, y, z) - fufal2 + fufal(x + h, y, z)) / h2
  d2 = (fufal(x, y - h, z) - fufal2 + fufal(x, y + h, z)) / h2
  d3 = (fufal(x, y, z - h) - fufal2 + fufal(x, y, z + h)) / h2
  Lappsi = -(d1 + d2 + d3) / 2 'druga poch. psi w punkcie (x,y,z)
  V = -1 / (Sqr(x * x + y * y + z * z))   'potencjal, tu  psi/psi=1
  En = En + Lappsi / psinowa + V  'sumowanie energii lokalnych
 Next i
  Cells(j, 1) = c
  Cells(j, 2) = En / llos 'zapis energii średniej
  j = j + 1
Next c
End Sub

Function fufal(x, y, z) 'oblicza wartość funkcji psi w punkcie x,y,z
  r = Sqr(x * x + y * y + z * z)
  fufal = Exp(-c * r)
End Function

Function GRNF() 'generuje liczbę pseudolosową z rozkładu Gaussa
  r1 = Sqr(-Log(1 - Rnd))
  GRNF = r1 * Sin(2 * pi * Rnd)
End Function

Wykres przedstawia wyniki obliczeń dla miliona losowań. Minimum znajduje się przy c = 1 i wynosi prawie dokładnie -0.5 hartree.

W poprzednim wpisie przedstawiłem algorytm obliczania energii atomu wodoru z wykorzystaniem metody Monte Carlo. Energie lokalne liczone były za pomocą numerycznego różniczkowania funkcji falowej w punkcie (x,y,z). Celem tego różniczkowania było obliczenie wartości laplasjanu w tym punkcie.
Ponieważ różniczkowanie takie można wykonać symbolicznie, procedurę można uprościć wpisując do programu symboliczną postać wyniku działania hamiltonianu na wybraną funkcję psi. Takie podejście jest mniej ogólne od numerycznego wyznaczania wartości laplasjanu, ale może ułatwić zrozumienie sposobu działania algorytmu Metropolisa.
Hamiltonian działający na funkcję psi ma postać (jednostki atomowe):

Dla funkcji psi postaci

Wynik działania hamiltonianu na tę funkcję wyraża się wzorem:

Wobec powyższego wzór na energię lokalną, używaną w algorytmie Monte Carlo, ma postać:

Fragment programu umieszczony w poprzednim wpisie, a odnoszący się do modułu całkowania (właściwie sumowania) upraszcza się do postaci:
...
'obliczanie cakłi z energii lokalnych
  r1 = SQR(x * x + y * y + z * z)
  En = En + (-c * c / 2 + (c - 1) / r1)
...
Wartość energii -0.5, jako minimum dla wartości c=1 otrzymuje się po dokonaniu sumowania 20000 konfiguracji.

W poprzednim poście pokazałem zapis modułu całkowania energii lokalnych z wykorzystaniem analitycznej postaci wyniku działania hamiltonianu dla atomu wodoru na funkcję exp(-cr). W niniejszym poście wykorzystałem to samo podejście i wyznaczyłem postać wyniku działania hamiltonianu dla atomu wodoru na funkcję gaussowską exp(-cr2):

Wzór na energię lokalną ma postać, jak niżej:


Funkcja programu QBASIC definiująca funkcję Gaussa w programie ma postać:

FUNCTION fufal (x, y, z)
  r = SQR(x * x + y * y + z * z)
  fufal = EXP(-c * r * r)
END FUNCTION
Odpowiedni moduł całkowania numerycznego sprowadza się do następujących instrukcji:
...
'obliczanie calki z energii lokalnych
  r1 = SQR(x * x + y * y + z * z)
  El = -2 * c * c * r1 * r1 - 1 / r1 + 3 * c
  En = En + El
...
Dla 500000 konfiguracji minimum dla c=0.3 wynosi -0.421 j.a., co w przeliczeniu na elektronowolty daje wartość -11.45 eV. Błąd wyliczenia w stosunku do dokładnej wartości energii wawynosi +15.8%.

W celu dokładnego zrozumienia sposobu obliczania energii atomu wodoru z wykorzystaniem metody Monte Carlo i algorytmu Metropolisa, napisałem program w języku QBASIC. Program wykorzystuje znany generator liczb pseudolosowych o rozkładzie normalnym. Aby przekonać się, że tak się dzieje w rzeczywistości wyniki losowań zapisałem w pliku, z którego wykonałem wykres za pomocą programu Excel. W programie umieściłem kod, który pozwala zliczać losowania w wektorze x:
'program GRNF generator lipselo o rozkladzie Gaussa
'zakres GRNF od -3.4 do 3.11 dla miliona losowan

pi = 3.14159265#

DIM x(-350 TO 350)

FOR i = 1 TO 100000
  r1 = SQR(-LOG(1 - RND))       'generowanie lipselo
  GRNF = r1 * SIN(2 * pi * RND)
  liczba = INT(GRNF * 100)      'zliczanie
  x(liczba) = x(liczba) + 1
NEXT i

OPEN "gauss.dat" FOR APPEND AS #1

FOR i = -350 TO 350
  PRINT #1, i, x(i) 'wpis wyniku do pliku
NEXT i

CLOSE

Zamieszczony poniżej wykres pokazuje, że generowane liczby pseudolosowe mieszczą się w zakresie od około -3.4 do około 3.2. Wartość średnia losowań jest bliska zera a maksymalna liczebność losowań średniej wynosi około 0.6% całkowitej liczby losowań:
Przedstawiony poprzednio wykres zależności częstości występowania promienia od jego wartości przeanalizowałem z wykorzystaniem postaci analitycznych funkcji. Kilka prób wykonanych za pomocą programu Derive pokazało, że dobrym przybliżeniem jest iloczyn funkcji Gaussa i kwadratu zmiennej niezależnej z odpowiednimi współczynnikami. Uzyskany wynik pokazuje poniższy wykres:

Uwaga. Ta aproksymacja nie jest zbyt dobra. Lepsza została pokazana w następnym wpisie.

Metoda Monte Carlo obliczania energii stanów atomu wodoru wykorzystuje algorytm Metropolisa wyboru punktów w przestrzeni wokółjądrowej. Dzięki temu wyborowi suma energii lokalnych aproksymuje energię całkowitą badanego stanu. Intrygowało mnie, które punkty są wybierane przez algorytm Metropolisa. Ze względu na fakt, że rozważany atom wodoru w stanie 1s jest kulistosymetryczny, wystarczyło zapytać, które wartości promienia wodzącego są wybierane i z jaką częstością.
W tym celu zmodyfikowałem program do obliczenia energii, umieszczony we Wprawce II. Usunąłem fragmenty obliczające energię lokalną i pozostawiłem tylko algorytm wyboru promienia. Dodałem procedurę zliczającą promienie. Zakres wektora liczności (6.2*100) ustaliłem eksperymentalnie dla 500000 losowań. Kod tak zmodyfikowanego programu ma następującą postać:
DECLARE FUNCTION fufal! (x!, y!, z!)
DECLARE FUNCTION GRNF! ()  'gaussowski generator pseudolosowy
                           'jednostki atomowe
CLS
SCREEN 12
llos = 500000           'liczba losowan
DIM SHARED c             'zmienna wariacyjna globalna
DIM x(620)               'wektor licznosci promieni
c = 1.5                  'wybrana wartosc zm. wariacyjnej
OPEN "dane.DAT" FOR APPEND AS #1

x = 0: y = 1.2: z = 0    'poczatkowy punkt
FOR i = 1 TO llos
  xzapas = x             'zabezpieczenie starych wspolrzednych
  yzapas = y
  zzapas = z

  psi = fufal(x, y, z)    'wartosc psi w punkcie (x,y,z)
  psikw = psi * psi       'kwadrat psi

           'Losowanie nowego punktu  (xn,yn,zn)
  xn = 2 * RND - 1        'zakres (-1, 1)
  yn = 2 * RND - 1
  zn = 2 * RND - 1

  pr = SQR(xn * xn + yn * yn + zn * zn)  'promien punktu (xn,yn,zn)
  skok = .6 * GRNF         'skok przypadkowy wg rozkladu Gaussa

  x = x + xn * skok / pr  'poprawione wspolrzedne nowego punktu
  y = y + yn * skok / pr
  z = z + zn * skok / pr
 
  psinowa = fufal(x, y, z)     'wartsc psi w nowym punkcie
  psinowakw = psinowa * psinowa

'obliczanie warunku przejscia lancucha do nowego punktu

 rel = psinowakw / psikw   'stosunek nowej i starej psi
  IF rel < 1 THEN          'przejscie bezwarunkowe gdy rel >= 1
    IF RND > rel THEN      'przejscie odrzucone
      x = xzapas           'przywrocenie starych wartosci
      y = yzapas
      z = zzapas
      psinowa = fufal(x, y, z)
    END IF
 END IF

  rn = SQR(x * x + y * y + z * z) 'promien do zliczania
  liczba = INT(rn * 100)     ' definicja adresu wektora promieni
  x(liczba) = x(liczba) + 1  ' zliczanie promieni
 NEXT i

FOR i = 1 TO 620
  PRINT #1, i, x(i)
NEXT i
CLOSE
END

FUNCTION fufal (x, y, z)
  r = SQR(x * x + y * y + z * z)
  fufal = EXP(-c * r)
END FUNCTION

FUNCTION GRNF
  r1 = SQR(-LOG(1 - RND))
  GRNF = r1 * SIN(2 * 3.14159265# * RND)
END FUNCTION

Program generuje zbiór danych, które można przedstawić graficznie. Poniżej zamieściłem wykres uzyskany za pomocą programu Excel:

Jak widać na wykresie, algorytm Metropolisa traktuje promienie w sposób wybiórczy. Uzyskana krzywa przypomina funkcję dystrybucji radialnej (radialnej gęstości elektronowej) stanu podstawowego atomu wodoru z maksimum poniżej jedności (w obliczeniach użyłem jednostki atomowe).

czwartek, 17 lutego 2011

4. Wprawka z całkowania za pomocą metody Monte Carlo

Metoda Monte Carlo (MC) opracowana przez Stanisława Ulama była mi znana, ale dotychczas nie używałem jej do żadnych celów. Zainteresowałem się tym zagadnieniem z powodu wielorakich zastosowań MC w obliczeniach energii i innych parametrów rozmaitych układów kwantowych. Szczególnie interesujące wydało mi się obliczanie energii poziomów energetycznych w atomach.
Aby jednak móc dobrać się do zagadnień kwantowych musiałem zrozumieć istotę całkowania za pomocą MC. W tym celu wybrałem szkolne zagadnienie obliczania powierzchni koła.
Piękno metody sprowadza się do tego, że oblicza się pole kwadratu opisanego na kole, którego pole chcemy policzyć. Pole kwadratu mnoży się przez pewien ułamek właściwy, który jest wynikiem działania procedury losowania. Wynik mnożenia daje pole koła w przybliżeniu. Dokładność przybliżenia zależy od liczby losowań oraz ich jakości.
W celu przeprowadzenia obliczeń należy znać na początku jedynie promień koła, którego pole chcemy policzyć. Z promienia łatwo obliczyć bok kwadratu opisanego i pole kwadratu.
Procedura losowania polega na losowym wyborze współrzędnych x,y wewnątrz i na brzegach kwadratu. Ze współrzędnych oblicza się promień punktu wylosowanego (pierwiastek z sumy kwadratów współrzędnych). Jeśli wylosowany punkt leży wewnątrz lub na brzegu koła, to zlicza się taki wypadek. Po wykonaniu wszystkich losowań należy sprawdzić ile razy koło zostało trafione. Pole koła dane jest wówczas wzorem:


Ponieważ należy przeprowadzić sporo losowań a ręczne obliczenia mogą nieco znużyć do sprawdzenie, czy rozumiem działanie ten metody zastosowałem programowanie komputerowe. Użyłem języka BASIC w wersji QBASIC.
Poniżej zamiesiłem kod programu i wyniki obliczeń:


Wyniki działania programu:


Idea jest genialna w swojej prostocie.

Dodatek styczeń 2020.

Trzymam się basica i dodaję program napisany w SmallBasicu, który robi to samo, ale przy większej liczbie losowań:

Wyniki obliczeń są widoczne w poniższym okienku