Differences
This shows you the differences between two versions of the page.
documentation:tutorials:model_examples_from_physics:harmonic_oscillator [2016/10/07 21:15] – created Maurits W. Haverkort | documentation:tutorials:model_examples_from_physics:harmonic_oscillator [2016/10/10 09:41] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | {{indexmenu_n> | ||
+ | ====== Harmonic oscillator ====== | ||
+ | ### | ||
+ | This example solves the Harmonic oscillator numerically on a basis of plane waves. | ||
+ | ### | ||
+ | |||
+ | <code Quanty Harmonic_oscillator.Quanty> | ||
+ | -- solves the Harmonic oscillator H = -1/2 (d^2/dx^2) + 1/2 x^2 | ||
+ | -- on a basis of complex plane waves | ||
+ | -- the plane wave basis assumes a periodicity, | ||
+ | a = 20 | ||
+ | -- maximum k (ikmax * 2 * pi/a) | ||
+ | ikmax = 60 | ||
+ | -- each plane wave is a basis " | ||
+ | NF = 2 * ikmax + 1 | ||
+ | -- integration steps | ||
+ | dxint = 0.0001 | ||
+ | |||
+ | -- we first define a set of functions that are used to create the operators using integrals over the wave-functions | ||
+ | |||
+ | -- the basis functions (plane waves) are: | ||
+ | function Psi(x, i) | ||
+ | k = 2 * pi * i / a | ||
+ | return (math.cos(k*x) + I * math.sin(k*x)) / math.sqrt(a) | ||
+ | end | ||
+ | |||
+ | -- evaluate <psi_i | -1/2 (d^2/dx^2) | psi_j> | ||
+ | function IntegrateKineticEnergy(i, | ||
+ | kj = 2 * pi * j / a | ||
+ | sum = 0 | ||
+ | for x=-a/2, a/2, dxint do | ||
+ | sum = sum - Conjugate(Psi(x, | ||
+ | end | ||
+ | return sum | ||
+ | end | ||
+ | |||
+ | -- the previous integral has an analytical solution | ||
+ | function IntegrateKineticEnergyAna(i, | ||
+ | if i==j then | ||
+ | return 2*(j*pi/ | ||
+ | else | ||
+ | return 0 | ||
+ | end | ||
+ | end | ||
+ | |||
+ | -- evaluate <psi_i | 1/2 x^2 | psi_j> | ||
+ | function IntegratePotentialEnergy(i, | ||
+ | kj = 2 * pi * j / a | ||
+ | sum = 0 | ||
+ | for x=-a/2, a/2, dxint do | ||
+ | sum = sum + Conjugate(Psi(x, | ||
+ | end | ||
+ | return sum | ||
+ | end | ||
+ | |||
+ | -- the previous integral has an analytical solution | ||
+ | function IntegratePotentialEnergyAna(i, | ||
+ | if i==j then | ||
+ | return (a^2)/24 | ||
+ | else | ||
+ | return a^2 * (2*(i-j) * pi * math.cos((i-j)*pi) + (-2+(i-j)^2*pi^2) * math.sin((i-j)*pi)) / (8 * (i-j)^3 * pi^3) | ||
+ | end | ||
+ | end | ||
+ | |||
+ | -- create the Hamiltonian | ||
+ | H = 0*NewOperator(" | ||
+ | for i=-ikmax, ikmax do | ||
+ | for j=-ikmax, ikmax do | ||
+ | H = H + (IntegrateKineticEnergyAna(i, | ||
+ | end | ||
+ | end | ||
+ | |||
+ | -- create the operator to measure the kinetic energy | ||
+ | Hkin = 0*NewOperator(" | ||
+ | for i=-ikmax, ikmax do | ||
+ | for j=-ikmax, ikmax do | ||
+ | Hkin = Hkin + IntegrateKineticEnergyAna(i, | ||
+ | end | ||
+ | end | ||
+ | |||
+ | -- create the operator to measure the potential energy | ||
+ | Hpot = 0*NewOperator(" | ||
+ | for i=-ikmax, ikmax do | ||
+ | for j=-ikmax, ikmax do | ||
+ | Hpot = Hpot + IntegratePotentialEnergyAna(i, | ||
+ | end | ||
+ | end | ||
+ | |||
+ | -- The operators "do not know" how many electrons there are in the system. | ||
+ | -- We can restrict the solutions to only find states with one electron | ||
+ | -- For this we create a string with 1's and 0's that tells the code which basis orbitals to include for this specific restriction (useful if one has core states) | ||
+ | -- and in restrictions we set the minimum and maximum occupation of these basis orbitals (min=1 and max=1 in our case) | ||
+ | restrictionstring = "" | ||
+ | for i=1, NF do | ||
+ | restrictionstring = restrictionstring .. " | ||
+ | end | ||
+ | StartRestrictions = {NF, 0, {restrictionstring, | ||
+ | |||
+ | |||
+ | -- we now can create the lowest Npsi eigenstates: | ||
+ | Npsi=10 | ||
+ | psiList = Eigensystem(H, | ||
+ | -- note that for small systems Eigensystem creates a dense matrix and uses dense methods. | ||
+ | -- The boarder between smal and big can be set, if you want to test the Lanczos algorithm as well | ||
+ | -- psiList = Eigensystem(H, | ||
+ | |||
+ | -- create output that lists the energy, kinetic energy and potential energy of the states found | ||
+ | oppList={H, | ||
+ | |||
+ | print(" | ||
+ | for key,psi in pairs(psiList) do | ||
+ | expvalue = psi * oppList * psi | ||
+ | for k,v in pairs(expvalue) do | ||
+ | io.write(string.format(" | ||
+ | end; | ||
+ | io.write(" | ||
+ | end | ||
+ | </ | ||
+ | |||
+ | ==== Result ==== | ||
+ | The output is: | ||
+ | <file Quanty_Output Harmonic_oscillator.out> | ||
+ | Start of BlockGroundState. Converge 10 states to an energy with relative variance smaller than 1.490116119384766E-06 | ||
+ | |||
+ | Start of BlockOperatorPsiSerialRestricted | ||
+ | Outer loop 1, Number of Determinants: | ||
+ | Start of BlockOperatorPsiSerialRestricted | ||
+ | Start of BlockGroundState. Converge 10 states to an energy with relative variance smaller than 1.490116119384766E-06 | ||
+ | |||
+ | Start of BlockOperatorPsiSerial | ||
+ | < | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | ===== Table of contents ===== | ||
+ | {{indexmenu> |