This tutorial can be downloaded link.
Advanced Tutorial 2: Detailed Analysis of QDET Many-Body States¶
In this tutorial, we show how the full diagonalization of the QDET effective Hamiltonian enables a detailed analysis of the excited states of the defect.
As we focus on the analysis in this tutorial, we download the input and output files from the QDET calculation. For more details about how to perform the underlying QDET calculations, see Basic Tutorial 5.
[1]:
%%bash
mkdir -p west.wfreq.save
wget -N -q https://west-code.org/doc/training/nv_diamond_63/wfreq.json -O west.wfreq.save/wfreq.json
Solution of QDET for \(m_S=0\)¶
We diagonalize the QDET Hamiltonian as usual:
[2]:
from westpy.qdet import QDETResult
# construct object for effective Hamiltonian
effective_hamiltonian = QDETResult(filename='west.wfreq.save/wfreq.json')
# diagonalize Hamiltonian
solution = effective_hamiltonian.solve()
_ _ _____ _____ _____
| | | | ___/ ___|_ _|
| | | | |__ \ `--. | |_ __ _ _
| |/\| | __| `--. \ | | '_ \| | | |
\ /\ / |___/\__/ / | | |_) | |_| |
\/ \/\____/\____/ \_/ .__/ \__, |
| | __/ |
|_| |___/
WEST version : 6.0.0
Today : 2024-06-19 10:23:19.682979
-----------------------------------------------------
===============================================================
Building effective Hamiltonian...
nspin: 1
occupations: [[2. 2. 2. 2. 1. 1.]]
===============================================================
diag[1RDM - 1RDM(GS)] | ||||||||
---|---|---|---|---|---|---|---|---|
E [eV] | char | 87 | 122 | 123 | 126 | 127 | 128 | |
0 | 0.000 | 3- | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 |
1 | 0.436 | 1- | -0.001 | -0.009 | -0.018 | -0.067 | 0.004 | 0.091 |
2 | 0.436 | 1- | -0.001 | -0.009 | -0.018 | -0.067 | 0.092 | 0.002 |
3 | 1.251 | 1- | -0.002 | -0.019 | -0.023 | -0.067 | 0.054 | 0.057 |
4 | 1.939 | 3- | -0.003 | -0.010 | -0.127 | -0.860 | 1.000 | 0.000 |
5 | 1.940 | 3- | -0.003 | -0.010 | -0.127 | -0.860 | 0.000 | 1.000 |
6 | 2.935 | 1- | -0.000 | -0.032 | -0.043 | -0.855 | 0.929 | 0.002 |
7 | 2.936 | 1- | -0.000 | -0.032 | -0.043 | -0.855 | 0.002 | 0.929 |
8 | 4.661 | 1- | -0.006 | -0.054 | -0.188 | -1.672 | 0.960 | 0.960 |
9 | 5.080 | 3- | -0.014 | -0.698 | -0.213 | -0.075 | 1.000 | 0.000 |
-----------------------------------------------------
The solution was obtained for 10 electrons (5 in each spin channel) and 6 orbitals:
[3]:
print(solution['nelec'])
print(solution['norb'])
(5, 5)
6
These numbers can be compared with the basis
and occupation
stored in the effective Hamiltonian.
[4]:
print(effective_hamiltonian.basis)
print(len(effective_hamiltonian.basis))
[ 87 122 123 126 127 128]
6
[5]:
import numpy as np
print(effective_hamiltonian.occupation)
print(np.sum(effective_hamiltonian.occupation))
[[2. 2. 2. 2. 1. 1.]]
10.0
This is the case of solutions with \(m_S=0\). We will later discuss the case with \(m_S=1\).
To check for the value of \(S^2\) and spin multiplicity, one can easily:
[6]:
for i, state in enumerate(solution['evcs']):
en = solution['evs'][i]
ss, mult = effective_hamiltonian.heff.spin_square_spin_polarized(state, norb=solution['norb'], nelec=solution['nelec'])
print(f"i={i}, energy [eV]={en:.3f}, <S^2>={ss:.3f}, mult={mult:.3f}")
i=0, energy [eV]=0.000, <S^2>=2.000, mult=3.000
i=1, energy [eV]=0.436, <S^2>=0.000, mult=1.000
i=2, energy [eV]=0.436, <S^2>=0.000, mult=1.000
i=3, energy [eV]=1.251, <S^2>=0.000, mult=1.000
i=4, energy [eV]=1.939, <S^2>=2.000, mult=3.000
i=5, energy [eV]=1.940, <S^2>=2.000, mult=3.000
i=6, energy [eV]=2.935, <S^2>=0.000, mult=1.000
i=7, energy [eV]=2.936, <S^2>=0.000, mult=1.000
i=8, energy [eV]=4.661, <S^2>=0.000, mult=1.000
i=9, energy [eV]=5.080, <S^2>=2.000, mult=3.000
The eigenstate of each many-body state is a matrix of size (number of Slater determinants in the spin-alpha channel, number of Slater determinants in the spin-beta channel), where each entry represents the contribution of that product of Slater determinants to the many-body states. We can determine the number of Slater determinants in each spin-channel as follows:
[7]:
from pyscf.fci import cistring
# print the number of possible Slater determinants in each spin channel
for ispin, spinlabel in enumerate(['alpha','beta']):
print(f'No. Slater determinants in spin-channel {spinlabel} = {len(cistring.make_strings(range(solution["norb"]),solution["nelec"][ispin]))}')
No. Slater determinants in spin-channel alpha = 6
No. Slater determinants in spin-channel beta = 6
We check that the shape of the eigenvector matrix is 6x6
[8]:
print(solution['evcs'][0].shape)
(6, 6)
We can now inspect the contribution of the various Slater determinants to a given excited many-body state.
[9]:
from westpy.qdet import visualize_correlated_state
for i, state in enumerate(solution['evcs']):
en = solution['evs'][i]
print(f'i= {i}, en [eV]={en}, ',visualize_correlated_state(state, solution['norb'], solution['nelec'], cutoff=10 **(-3)))
print( )
i= 0, en [eV]=0.0, -0.707|011111>|101111>+0.707|101111>|011111>
i= 1, en [eV]=0.4359576505738596, +0.313|011111>|011111>+0.596|011111>|101111>-0.035|011111>|110111>-0.018|011111>|111011>+0.012|011111>|111101>+0.004|011111>|111110>+0.596|101111>|011111>-0.312|101111>|101111>+0.180|101111>|110111>+0.093|101111>|111011>-0.064|101111>|111101>-0.021|101111>|111110>-0.035|110111>|011111>+0.180|110111>|101111>-0.018|111011>|011111>+0.093|111011>|101111>+0.012|111101>|011111>-0.064|111101>|101111>+0.004|111110>|011111>-0.021|111110>|101111>
i= 2, en [eV]=0.43629670382916214, +0.596|011111>|011111>-0.312|011111>|101111>-0.180|011111>|110111>-0.093|011111>|111011>+0.064|011111>|111101>+0.021|011111>|111110>-0.312|101111>|011111>-0.595|101111>|101111>-0.035|101111>|110111>-0.018|101111>|111011>+0.012|101111>|111101>+0.004|101111>|111110>-0.180|110111>|011111>-0.035|110111>|101111>-0.093|111011>|011111>-0.018|111011>|101111>+0.064|111101>|011111>+0.012|111101>|101111>+0.021|111110>|011111>+0.004|111110>|101111>
i= 3, en [eV]=1.2505228566304396, +0.687|011111>|011111>+0.688|101111>|101111>-0.145|110111>|110111>-0.082|110111>|111011>+0.074|110111>|111101>+0.022|110111>|111110>-0.082|111011>|110111>-0.051|111011>|111011>+0.046|111011>|111101>+0.014|111011>|111110>+0.074|111101>|110111>+0.046|111101>|111011>-0.040|111101>|111101>-0.012|111101>|111110>+0.022|111110>|110111>+0.014|111110>|111011>-0.012|111110>|111101>-0.007|111110>|111110>
i= 4, en [eV]=1.9393654779292357, +0.656|011111>|110111>+0.252|011111>|111011>-0.070|011111>|111101>-0.037|011111>|111110>+0.013|101111>|110111>+0.005|101111>|111011>-0.001|101111>|111101>-0.656|110111>|011111>-0.013|110111>|101111>-0.252|111011>|011111>-0.005|111011>|101111>+0.070|111101>|011111>+0.001|111101>|101111>+0.037|111110>|011111>
i= 5, en [eV]=1.940122558236312, +0.013|011111>|110111>+0.005|011111>|111011>-0.001|011111>|111101>-0.656|101111>|110111>-0.252|101111>|111011>+0.070|101111>|111101>+0.037|101111>|111110>-0.013|110111>|011111>+0.656|110111>|101111>-0.005|111011>|011111>+0.252|111011>|101111>+0.001|111101>|011111>-0.070|111101>|101111>-0.037|111110>|101111>
i= 6, en [eV]=2.9352449224310595, +0.176|011111>|011111>-0.061|011111>|101111>+0.653|011111>|110111>+0.146|011111>|111011>+0.127|011111>|111101>+0.004|011111>|111110>-0.061|101111>|011111>-0.176|101111>|101111>+0.027|101111>|110111>+0.006|101111>|111011>+0.005|101111>|111101>+0.653|110111>|011111>+0.027|110111>|101111>+0.146|111011>|011111>+0.006|111011>|101111>+0.127|111101>|011111>+0.005|111101>|101111>+0.004|111110>|011111>
i= 7, en [eV]=2.9363046696777113, -0.061|011111>|011111>-0.176|011111>|101111>-0.027|011111>|110111>-0.006|011111>|111011>-0.005|011111>|111101>-0.176|101111>|011111>+0.061|101111>|101111>+0.653|101111>|110111>+0.146|101111>|111011>+0.127|101111>|111101>+0.004|101111>|111110>-0.027|110111>|011111>+0.653|110111>|101111>-0.006|111011>|011111>+0.146|111011>|101111>-0.005|111101>|011111>+0.127|111101>|101111>+0.004|111110>|101111>
i= 8, en [eV]=4.660579248302518, -0.141|011111>|011111>-0.141|101111>|101111>-0.856|110111>|110111>-0.294|110111>|111011>+0.125|110111>|111101>+0.049|110111>|111110>-0.294|111011>|110111>-0.084|111011>|111011>+0.018|111011>|111101>+0.009|111011>|111110>+0.125|111101>|110111>+0.018|111101>|111011>+0.106|111101>|111101>+0.016|111101>|111110>+0.049|111110>|110111>+0.009|111110>|111011>+0.016|111110>|111101>+0.006|111110>|111110>
i= 9, en [eV]=5.079583342421291, +0.194|011111>|110111>-0.326|011111>|111011>+0.591|011111>|111101>+0.084|011111>|111110>+0.004|101111>|110111>-0.006|101111>|111011>+0.011|101111>|111101>+0.002|101111>|111110>-0.194|110111>|011111>-0.004|110111>|101111>+0.326|111011>|011111>+0.006|111011>|101111>-0.591|111101>|011111>-0.011|111101>|101111>-0.084|111110>|011111>-0.002|111110>|101111>
The ground state is a linear combination of products of two Slater determinants, namely \(|011111\rangle| 101111\rangle\), where the first one (\(|011111\rangle\)) is the Slater determinant in the alpha-channel, and the second one (\(|101111\rangle\)) is the determinant in the beta-channel.
Slater determinants are in the Fock representation, where the orbital with the lowest energy is on the right. For example, \(|011111\rangle\) means that the 5 orbitals with the lowest energy are occupied and the orbital with the highest energy is unoccupied.
Finally, the cutoff
in visualize_correlated_state
is the cutoff for Slater determinants. Only Slater determinants with prefactors larger (in absolute value) than the cutoff are printed.
We can visualize the contribution of the various Slater determinants to a given excited many-body state.
[10]:
import matplotlib.pyplot as plt
index1 = 0
index2 = 1
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
ax1.set_title('Ground state')
ax2.set_title('1st Excited state')
ax1.set_xlabel('Slater determinant index')
ax1.set_ylabel('Contribution of Slater determinant')
ax2.set_xlabel('Slater determinant index')
ax1.bar([i for i in range(solution['evcs'][index1].flatten().shape[0])],
abs(solution['evcs'][index1].flatten()))
ax2.bar([i for i in range(solution['evcs'][index2].flatten().shape[0])],
abs(solution['evcs'][index2].flatten()))
plt.show()
Solution of QDET for \(m_S=1\)¶
We demonstrate how to diagonalize the effective Hamiltonian for \(m_S=1\). In this case, the alpha spin channel will have more electrons than the beta spin channel.
We diagonalize the effective Hamiltonian choosing manually the number of electrons.
[12]:
from westpy.qdet import QDETResult
# construct object for effective Hamiltonian
effective_hamiltonian = QDETResult(filename='west.wfreq.save/wfreq.json')
nelec=(int(np.sum(effective_hamiltonian.occupation)//2)+1,int(np.sum(effective_hamiltonian.occupation)//2)-1)
print(nelec)
# diagonalize Hamiltonian
solution = effective_hamiltonian.solve(nelec=nelec)
(6, 4)
-----------------------------------------------------
===============================================================
Building effective Hamiltonian...
nspin: 1
occupations: [[2. 2. 2. 2. 1. 1.]]
===============================================================
diag[1RDM - 1RDM(GS)] | ||||||||
---|---|---|---|---|---|---|---|---|
E [eV] | char | 87 | 122 | 123 | 126 | 127 | 128 | |
0 | 0.000 | 3- | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 | 0.000 |
1 | 1.939 | 3- | -0.003 | -0.010 | -0.127 | -0.860 | 1.000 | 0.000 |
2 | 1.940 | 3- | -0.003 | -0.010 | -0.127 | -0.860 | 0.000 | 1.000 |
3 | 5.080 | 3- | -0.014 | -0.698 | -0.213 | -0.075 | 1.000 | 0.000 |
4 | 5.080 | 3- | -0.014 | -0.698 | -0.213 | -0.075 | 0.000 | 1.000 |
5 | 6.163 | 3- | -0.001 | -0.278 | -0.657 | -0.064 | 0.999 | 0.001 |
6 | 6.163 | 3- | -0.001 | -0.278 | -0.657 | -0.064 | 0.001 | 0.999 |
7 | 7.030 | 3- | -0.017 | -0.691 | -0.353 | -0.939 | 1.000 | 1.000 |
8 | 8.016 | 3- | -0.003 | -0.303 | -0.761 | -0.933 | 1.000 | 1.000 |
9 | 11.138 | 3- | -0.019 | -0.976 | -0.877 | -0.127 | 1.000 | 1.000 |
-----------------------------------------------------
We see that we have found only triplet states. In order to find singlet and triplet states, it is necessary to have \(m_S=0\), which is the assumption made by default in the solve
method.