# Operators as matrices

In the first example we show a small script written in Quanty that works and does not require further programming. The script creates the spin, angular momentum and Coulomb operator as matrices on a many body basis. The file conf.in defines the angular momentum of the shell and the number of electrons in this shell. We recommend to understand the quantum mechanics presented in this script, i.e. why are there 15 states for two electrons in the $p$ shell, but not to look into the script too much. You can come back to this after example 5.

The configuration file is:

config.in
-- Angular momentum of the shell (0=="s" 1=="p" 2=="d" 3=="f")
l = 1
-- Number of electrons
Nelec = 1

The output is:

Operators_as_Matrices.out
=============================================================
--> This small program will print out the possible many-body states for a given electronic configuration
--> The obtained states of single Slater determinants will be used as a Hilbert space for several operators.

=============================================================

Calculating all possible Slater determinants for a shell with angular momentum 1 and a filling of 1 electrons

======================== O U T P U T ========================

A shell with l= 1 and a filling of 1 electrons has Binomial(6 1) = 6 possible single Slater determinants
--> List of possible single Slater determinants which span the basis for all many body states:
1 |100000>
2 |010000>
3 |001000>
4 |000100>
5 |000010>
6 |000001>

=============================================================
The Sz operator on a basis Single slater determinants for a shell with l = 1 and a filling of 1 electrons is:
1 |100000>  -0.50  0.00  0.00  0.00  0.00  0.00
2 |010000>   0.00  0.50  0.00  0.00  0.00  0.00
3 |001000>   0.00  0.00 -0.50  0.00  0.00  0.00
4 |000100>   0.00  0.00  0.00  0.50  0.00  0.00
5 |000010>   0.00  0.00  0.00  0.00 -0.50  0.00
6 |000001>   0.00  0.00  0.00  0.00  0.00  0.50

=============================================================
The Lz operator on a basis Single slater determinants for a shell with l = 1 and a filling of 1 electrons is:
1 |100000>  -1.00  0.00  0.00  0.00  0.00  0.00
2 |010000>   0.00 -1.00  0.00  0.00  0.00  0.00
3 |001000>   0.00  0.00  0.00  0.00  0.00  0.00
4 |000100>   0.00  0.00  0.00  0.00  0.00  0.00
5 |000010>   0.00  0.00  0.00  0.00  1.00  0.00
6 |000001>   0.00  0.00  0.00  0.00  0.00  1.00

=============================================================
The S^2 operator on a basis Single slater determinants for a shell with l = 1 and a filling of 1 electrons is:
1 |100000>   0.75  0.00  0.00  0.00  0.00  0.00
2 |010000>   0.00  0.75  0.00  0.00  0.00  0.00
3 |001000>   0.00  0.00  0.75  0.00  0.00  0.00
4 |000100>   0.00  0.00  0.00  0.75  0.00  0.00
5 |000010>   0.00  0.00  0.00  0.00  0.75  0.00
6 |000001>   0.00  0.00  0.00  0.00  0.00  0.75

=============================================================
The L^2 operator on a basis Single slater determinants for a shell with l = 1 and a filling of 1 electrons is:
1 |100000>   2.00  0.00  0.00  0.00  0.00  0.00
2 |010000>   0.00  2.00  0.00  0.00  0.00  0.00
3 |001000>   0.00  0.00  2.00  0.00  0.00  0.00
4 |000100>   0.00  0.00  0.00  2.00  0.00  0.00
5 |000010>   0.00  0.00  0.00  0.00  2.00  0.00
6 |000001>   0.00  0.00  0.00  0.00  0.00  2.00

=============================================================
The Coulomb operator for a shell with l = 1 is given by 2 different operators depending on the angular momentum of the expansion of 1/|r1-r2| in spherical Harmonics
=============================================================
F[0]
1 |100000>   0.00  0.00  0.00  0.00  0.00  0.00
2 |010000>   0.00  0.00  0.00  0.00  0.00  0.00
3 |001000>   0.00  0.00  0.00  0.00  0.00  0.00
4 |000100>   0.00  0.00  0.00  0.00  0.00  0.00
5 |000010>   0.00  0.00  0.00  0.00  0.00  0.00
6 |000001>   0.00  0.00  0.00  0.00  0.00  0.00
=============================================================
F[2]
1 |100000>   0.00  0.00  0.00  0.00  0.00  0.00
2 |010000>   0.00  0.00  0.00  0.00  0.00  0.00
3 |001000>   0.00  0.00  0.00  0.00  0.00  0.00
4 |000100>   0.00  0.00  0.00  0.00  0.00  0.00
5 |000010>   0.00  0.00  0.00  0.00  0.00  0.00
6 |000001>   0.00  0.00  0.00  0.00  0.00  0.00

=============================================================
Timing results
Total_time | NumberOfRuns | Running | Name
0:00:00 |            1 |       0 | Create Determinants
0:00:00 |            1 |       0 | Create operators in second quantization
0:00:00 |            1 |       0 | Create operators in matrix form

For completeness, the actual code is:

Operators_as_Matrices.Quanty
-- script contributed by Yaroslav Kvashnin.

-- In order to simplify the program later on we first define some
-- functions.

-- Function which swaps two character in a string. It will be used
-- to check all possible particles permutations.
------------------------------------------------
function swap_char(pos1, pos2, str)
r=tostring((tonumber(str:sub(pos1,pos1))+3) % 2)
z=tostring((tonumber(str:sub(pos2,pos2))+3) % 2)
if (r ~= z) then
return str:sub(1, pos1-1) .. r .. str:sub(pos1+1,pos2-1) .. z .. str:sub(pos2+1)
else
return str
end
end
------------------------------------------------

-- begin of program
print("")
print("=============================================================")
print("--> This small program will print out the possible many-body states for a given electronic configuration");
print("--> The obtained states of single Slater determinants will be used as a Hilbert space for several operators.")
print("")
print("=============================================================")
print("")

dofile("conf.in")

print("Calculating all possible Slater determinants for a shell with angular momentum "..l.." and a filling of "..Nelec.." electrons")

-- Create the basis for quanty, define spin-orbitals and relate them
-- to atomic shells. There are 4*l+2 spin-orbitals in a shell with
-- angular momentum l. We label the spin-orbitals in the order from
-- ml=-l to ml=l alternating down and up.

Nf=4*l+2
IndexDn={}
IndexUp={}
j=1
for i=0,Nf-1,2 do
IndexDn[j]=i
IndexUp[j]=i+1
j=j+1
end

-- number of bosons
Nb=0

print("")
print("======================== O U T P U T ========================")
print("")

-- Number of many particle states.
Nstates=math.Binomial(Nf,Nelec)

print("A shell with l= "..l.." and a filling of "..Nelec.." electrons has Binomial("..Nf.." "..Nelec..") = "..Nstates.." possible single Slater determinants")

if(Nstates>3500) then
print("If you want to calculate more than 3500 states you have to remove this if then else from the script")
os.exit()
end
if(Nstates>64000) then
print("If you want to calculate more than 64000 states you have to remove this if then else from the script")
print("Furthermore it is recommended that you set the number of bits in the hash key table to a larger number.")
print("Change the line psi[i] = NewWavefunction(Nf, Nb, {{basis[i-1],1}})")
print("to psi[i] = NewWavefunction(Nf, Nb, {{basis[i-1],1}}, {{\"NBitsKey\",20}}).")
os.exit()
end

TimeStart("Create Determinants")

-- Create the first determinant (spin-orbital 1
-- to Nelec filled, Nelec+1 to Nf empty).
-- Determinants are stored as strings with 1
-- meaning occupied and 0 meaning empty
str=""
for i=1,Nelec do
str=str..1
end
for i=1,Nf-Nelec do
str=str..0
end

-- Search possible many-body states
newstr={}; newstr[0]=str
basis={};
for i=1,Nstates do
basis[i]=str
end
kprev={} ; kprev[1]=0 ; kprev[2]=0 ; k=0 ; e=1
for i=1,Nf do
for l=kprev[i],kprev[i+1] do
for j=i+1,Nf do
k=k+1
newstr[k]=swap_char(i,j,newstr[l])
info=0
for g=1,Nstates do
if (newstr[k] == basis[g]) then
info=1
end
end
if (info == 0) then
e=e+1
basis[e]=newstr[k]
end
end
if (e == Nstates) then
break
end
end
kprev[i+2]=k
end
-- END of search

TimeEnd("Create Determinants")

-- print the possible many-body single Slater
-- determinant states
print("--> List of possible single Slater determinants which span the basis for all many body states:")
for i=1,(Nstates) do
print(string.format("%5i |%s>",i,basis[i]))
end

TimeStart("Create operators in second quantization")

OppSz   = NewOperator("Sz"   ,Nf,IndexUp,IndexDn)
OppLz   = NewOperator("Lz"   ,Nf,IndexUp,IndexDn)
OppSsqr = NewOperator("Ssqr" ,Nf,IndexUp,IndexDn)
OppLsqr = NewOperator("Lsqr" ,Nf,IndexUp,IndexDn)
OppJz   = NewOperator("Jz"   ,Nf,IndexUp,IndexDn)
OppJsqr = NewOperator("Jsqr" ,Nf,IndexUp,IndexDn)
Oppldots= NewOperator("ldots",Nf,IndexUp,IndexDn)

SlaterInts={}
OppFk={}
Nk=l+1
for j=1,Nk do
for i = 1,Nk do
SlaterInts[i]=0
end
SlaterInts[j]=1
OppFk[j] = NewOperator("U", Nf, IndexUp, IndexDn, SlaterInts)
end

TimeEnd("Create operators in second quantization")

TimeStart("Create operators in matrix form")

--- create the set of wavefunctions, using the obtained states
psi={}
for i=1,Nstates do
psi[i] = NewWavefunction(Nf,Nb,{{basis[i],1}})
end

print("\n=============================================================")
print("The Sz operator on a basis Single slater determinants for a shell with l = "..l.." and a filling of "..Nelec.." electrons is:")
for i = 1, Nstates do
io.write(string.format("%5i |%s>  ",i,basis[i]))
for j = 1, Nstates do
io.write(string.format("%5.2f ",psi[i] * OppSz * psi[j]))
end
io.write("\n")
end

print("\n=============================================================")
print("The Lz operator on a basis Single slater determinants for a shell with l = "..l.." and a filling of "..Nelec.." electrons is:");
for i = 1, Nstates do
io.write(string.format("%5i |%s>  ",i,basis[i]))
for j = 1, Nstates do
io.write(string.format("%5.2f ",psi[i] * OppLz * psi[j]));
end
io.write("\n");
end

print("\n=============================================================")
print("The S^2 operator on a basis Single slater determinants for a shell with l = "..l.." and a filling of "..Nelec.." electrons is:")
for i = 1, Nstates do
io.write(string.format("%5i |%s>  ",i,basis[i]))
for j = 1, Nstates do
io.write(string.format("%5.2f ",psi[i] * OppSsqr * psi[j]))
end
io.write("\n")
end

print("\n=============================================================")
print("The L^2 operator on a basis Single slater determinants for a shell with l = "..l.." and a filling of "..Nelec.." electrons is:")
for i = 1, Nstates do
io.write(string.format("%5i |%s>  ",i,basis[i]))
for j = 1, Nstates do
io.write(string.format("%5.2f ",psi[i] * OppLsqr * psi[j]))
end
io.write("\n")
end

print("\n=============================================================")
print("The Coulomb operator for a shell with l = "..l.." is given by "..Nk.." different operators depending on the angular momentum of the expansion of 1/|r1-r2| in spherical Harmonics")
for k=1,Nk do
print("=============================================================")
print("F["..(2*(k-1)).."]")
for i = 1, Nstates do
io.write(string.format("%5i |%s>  ",i,basis[i]))
for j = 1, Nstates do
io.write(string.format("%5.2f ",psi[i] * OppFk[k] * psi[j]))
end
io.write("\n")
end
end

TimeEnd("Create operators in matrix form")

print("\n=============================================================")
TimePrint()