def diagonalize(ten_dq, umat): emat = edrixs.cb_op(edrixs.cf_cubic_d(ten_dq), edrixs.tmat_c2r('d', ispin=True)) H = (edrixs.build_opers(4, umat, basis) + edrixs.build_opers(2, emat, basis)) e, v = scipy.linalg.eigh(H) return e - e.min()
def diagonlize(scaleU=1): umat = edrixs.get_umat_slater('d', slater[0][1]*scaleU, slater[1][1]*scaleU, slater[2][1]*scaleU) cfmat = edrixs.angular_momentum.cf_tetragonal_d(ten_dq=ten_dq, d1=d1, d3=d3) H = edrixs.build_opers(2, cfmat, basis) + edrixs.build_opers(4, umat, basis) e, v = scipy.linalg.eigh(H) e = e - np.min(e) # define ground state as zero energy return e, v
def diagonalize(U, t, extra_emat=None): """Diagonalize 2 site Hubbard Hamiltonian""" umat = np.zeros((norb, norb, norb, norb), dtype=np.complex128) emat = np.zeros((norb, norb), dtype=np.complex128) U_mat_1site = edrixs.get_umat_slater('s', U) umat[:2, :2, :2, :2,] = umat[2:, 2:, 2:, 2:] = U_mat_1site emat[2, 0] = emat[3, 1] = emat[0, 2] = emat[1, 3] = t if extra_emat is not None: emat = emat + extra_emat H = (edrixs.build_opers(2, emat, basis) + edrixs.build_opers(4, umat, basis)) e, v = scipy.linalg.eigh(H) return e, v
# quantum number of orbital angular momentum for t2g: l=1 ll = 1 # Matrices of lx,ly,lz,sx,sy,sz,jx,jy,jz in the single-particle basis # lx: l_orb[0], ly: l_orb[1], lz: l_orb[2] l_orb = edrixs.get_orb_momentum(ll, True) # sx: s_spin[0], sy: s_spin[1], sz: s_spin[2] s_spin = edrixs.get_spin_momentum(ll) # jx: j_so[0], jy: j_so[1], jz: j_so[2] j_so = l_orb + s_spin # very small Zeeman splitting along z-direction emat_zeeman = (l_orb[2] + s_spin[2]) * 1e-10 # many-body operators of L^2, Lz Lxyz = edrixs.build_opers(2, l_orb, basis) L2 = np.dot(Lxyz[0], Lxyz[0]) + np.dot(Lxyz[1], Lxyz[1]) + np.dot( Lxyz[2], Lxyz[2]) Lz = Lxyz[2] # many-body operators of S^2, Sz Sxyz = edrixs.build_opers(2, s_spin, basis) S2 = np.dot(Sxyz[0], Sxyz[0]) + np.dot(Sxyz[1], Sxyz[1]) + np.dot( Sxyz[2], Sxyz[2]) Sz = Sxyz[2] # many-body operators of J^2, Jz Jxyz = edrixs.build_opers(2, j_so, basis) J2 = np.dot(Jxyz[0], Jxyz[0]) + np.dot(Jxyz[1], Jxyz[1]) + np.dot( Jxyz[2], Jxyz[2]) Jz = Jxyz[2] # We can also calculate the expectation values of the occupancy number of
sx = edrixs.get_sx(v_orbl) sy = edrixs.get_sy(v_orbl) sz = edrixs.get_sz(v_orbl) zeeman = ext_B[0] * (2 * sx) + ext_B[1] * (2 * sy) + ext_B[2] * (2 * sz) emat_chb[0:norb_d, 0:norb_d] += zeeman ################################################################################ # Build the Fock basis and Hamiltonain and Diagonalize # ------------------------------------------------------------------------------ # We create the fock basis and build the Hamiltonian using the full set of # :math:`20` spin orbitals, specifying that they are occuplied by :math:`18` # electrons. See the :ref:`sphx_glr_auto_examples_example_0_ed_calculator.py` # example for more details if needed. We also set the ground state to zero # energy. basis = np.array(edrixs.get_fock_bin_by_N(ntot, v_noccu)) H = (edrixs.build_opers(2, emat_chb, basis) + edrixs.build_opers(4, umat, basis)) e, v = scipy.linalg.eigh(H) e -= e[0] ################################################################################ # State analysis # ------------------------------------------------------------------------------ # Now we have all the eigenvectors in the Fock basis, we need to pick out the # states that have 8, 9 and 10 :math:`d`-electrons, respectively. # The modulus squared of these coeffcients need to be added up to get # :math:`\alpha`, :math:`\beta`, and :math:`\gamma`. num_d_electrons = basis[:, :norb_d].sum(1)
# electrons, the edrixs convention is to list the valence electrons first. ################################################################################ # Transform interactions into Fock basis # ------------------------------------------------------------------------------ # edrixs works by creating a Hamiltonian matrix :math:`\hat{H}` transformed into # this Fock basis. These are four fermion interactions with this form # # .. math:: # \hat{H} = <F_l|\sum_{ij}U_{ijkl}\hat{f}_{i}^{\dagger} # \hat{f}_{j}^{\dagger} # \hat{f}_{k}\hat{f}_{l}|F_r> # # generated as n_fermion = 4 H = edrixs.build_opers(n_fermion, umat, basis) ################################################################################ # We needed to specify :code:`n_fermion = 4` because the # :code:`edrixs.build_opers` function can also make two fermion terms. ################################################################################ # Diagonalize the matrix # ------------------------------------------------------------------------------ # For a small problem such as this it is convenient to use the native # `scipy <https://scipy.org>`_ diagonalization routine. This returns eigenvalues # :code:`e` and eignvectors :code:`v` where eigenvalue :code:`e[i]` corresponds # to eigenvector :code:`v[:,i]`. e, v = scipy.linalg.eigh(H) print("{} eignvalues and {} eigvenvectors {} elements long.".format( len(e), v.shape[1], v.shape[0]))
# :math:`|zx,\uparrow>`, :math:`|zx,\downarrow>`, etc. # In this basis, they take a simple form: only the diagonal terms have element # 1. We therefore make a 3D empty array and assign the diagonal as 1. Check # out the # `numpy indexing notes <https://numpy.org/doc/stable/reference/arrays.indexing.html>`_ # if needed. nd_real_harmoic_basis = np.zeros((norb, norb, norb), dtype=np.complex) indx = np.arange(norb) nd_real_harmoic_basis[indx, indx, indx] = 1 ################################################################################ # Recalling the necessity to put everything in the same basis, we transform # into the complex harmonic basis and then transform into our Fock basis nd_complex_harmoic_basis = edrixs.cb_op(nd_real_harmoic_basis, edrixs.tmat_r2c('d', True)) nd_op = edrixs.build_opers(2, nd_complex_harmoic_basis, basis) ################################################################################ # We apply the operator and print out as follows. Check the # `numpy docs <https://numpy.org/doc/1.18/reference/generated/numpy.reshape.html>`_ # if the details of how the spin pairs have been added up is not immediately # transparent. nd_expt = np.array( [edrixs.cb_op(nd_vec, v).diagonal().real for nd_vec in nd_op]) message = "{:>3s}" + "\t{:>6s}" * 5 print(message.format(*"E 3z2-r2 zx zy x2-y2 xy".split(" "))) message = "{:>3.1f}" + "\t{:>6.1f}" * 5 for evalue, row in zip(e, nd_expt.T): spin_pairs = row.reshape(-1, 2).sum(1)
# The large :math:`U` limit # ------------------------------------------------------------------------------ # Let us see what happens with :math:`U \gg t`. e, v = diagonalize(1000, 1) print("Energies are") print(e) ################################################################################ # To analyze what is going on we can determine the spin expectation values # of the cluster. Building the operators follows the same form as the # Hamiltonian and the previous example. spin_mom_one_site = edrixs.get_spin_momentum(ll) spin_mom = np.zeros((3, norb, norb), dtype=np.complex128) spin_mom[:, :2, :2] = spin_mom[:, 2:, 2:] = spin_mom_one_site opS = edrixs.build_opers(2, spin_mom, basis) opS_squared = (np.dot(opS[0], opS[0]) + np.dot(opS[1], opS[1]) + np.dot(opS[2], opS[2])) ################################################################################ # This time let us include a tiny magnetic field along the :math:`z`-axis, so # that we have a well-defined measurement axis and print out the expectation # values. zeeman = np.zeros((norb, norb), dtype=np.complex128) zeeman[:2, :2] = zeeman[2:, 2:] = 1e-8*spin_mom_one_site[2] e, v = diagonalize(1000, 1, extra_emat=zeeman) Ssq_exp = edrixs.cb_op(opS_squared, v).diagonal().real Sz_exp = edrixs.cb_op(opS[2], v).diagonal().real header = "{:<10s}\t{:<6s}\t{:<6s}"
# prepare files for ed.x # write control parameters to file edrixs.write_config(ed_solver=2, num_val_orbs=norbs, neval=100, ncv=200, nvector=1, idump=True) # write nonzeros terms of two-fermion terms hsoc_i to file 'hopping_i.in', read by ed.x edrixs.write_emat(hsoc_i, 'hopping_i.in', 1E-10) # write nonzeros terms of four-fermion terms umat to file 'coulomb_i.in', read by ed.x edrixs.write_umat(umat_i, 'coulomb_i.in', 1E-10) # write fock basis of decimal format to file 'fock_i.in', read by ed.x edrixs.write_fock_dec_by_N(norbs, noccu, "fock_i.in") # we also use pure Python ED solver to get the eigenvalues print("edrixs >>> building Fock basis ...") basis_i = edrixs.get_fock_bin_by_N(norbs, noccu) print("edrixs >>> Done!") print("edrixs >>> building Hamiltonian ...") H = edrixs.build_opers(2, hsoc_i, basis_i) H += edrixs.build_opers(4, umat_i, basis_i) print("edrixs >>> Done!") print("edrixs >>> diagonalize Hamiltonian ...") eval_i, evec_i = scipy.linalg.eigh(H) edrixs.write_tensor(eval_i, "eval_i.dat", fmt_float='{:20.10f}') print("edrixs >>> Done!")
# set print options np.set_printoptions(precision=6, linewidth=200, suppress=True) # number of orbitals norb = 6 # number of occupancy noccu = 2 # Slater integrals F0, F2 = 4.0, 1.0 # Coulomb interaction tensor umat = edrixs.get_umat_slater('p', F0, F2) # build Fock basis basis = edrixs.get_fock_bin_by_N(norb, noccu) # build Hamiltonian, four fermion terms H = edrixs.build_opers(4, umat, basis) # do ED e1, v1 = scipy.linalg.eigh(H) # add spin-orbit coupling (SOC) soc = edrixs.atom_hsoc('p', 0.2) # build Hamiltonian, two_fermion terms H2 = H + edrixs.build_opers(2, soc, basis) # do ED e2, v2 = scipy.linalg.eigh(H2) orb_mom = edrixs.get_orb_momentum(1, True) spin_mom = edrixs.get_spin_momentum(1) tot_mom = orb_mom + spin_mom opL, opS, opJ = edrixs.build_opers(2, [orb_mom, spin_mom, tot_mom], basis) # L^2 = Lx^2 + Ly^2 +Lz^2, S^2 = Sx^2 + Sy^2 + Sz^2, J^2 = Jx^2 + Jy^2 + Jz^2 L2 = np.dot(opL[0], opL[0]) + np.dot(opL[1], opL[1]) + np.dot(opL[2], opL[2])