.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/example_03_AIM_XAS.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_example_03_AIM_XAS.py: Anderson impurity model for NiO XAS ================================================================================ Here we calculate the :math:`L`-edge XAS spectrum of an Anderson impurity model, which is sometimes also called a charge-transfer multiplet model. This model considers a set of correlated orbitals, often called the impurity or metal states, that hybridize with a set of uncorrelated orbitals, often called the ligands or bath states. Everyone's favorite test case for x-ray spectroscopic calculations of the Anderson impurity model is NiO and we won't risk being original! This means that our correlated states will be the Ni :math:`3d` orbitals and the uncorrelated states come from O :math:`2p` orbitals. The fact that we include these interactions means that our spectrum can include processes where electrons transition from the bath to the impurity, as such the Anderson Impurity Model is often more accurate than atomic models, especially if the material has strong covalency. When defining the bath states, it is useful to use the so-called symmetry adapted linear combinations of orbitals as the basis. These states take into account the symmetry relationships between the different bath atom orbitals and the fact that there are bath orbital combinations that do not interact with the impurity by symmetry. By doing this the problem can be represented with fewer orbitals, which makes the calculation far more efficient. The standard EDRIXS solver that we will use assumes that the bath states are represented by an integer number of bath sites set by :code:`nbath`, each of which hosts the same number of spin-orbitals as the impurity e.g. 10 for a :math:`d`-electron material. NiO has a rocksalt structure in which all Ni atoms are surrounded by six O atoms. This NiO cluster used to simulate the crystal would then contain 10 Ni :math:`3d` spin-orbitals and :math:`6` spin-orbitals per O :math:`\times 6` O atoms :math:`=36` oxygen spin-orbitals. As explained by, for example, Maurits Haverkort et al. in [1]_ symmetry allows us to represent the bath with 10 symmetry adapted linear combinations of the different O :math:`p_x, p_y, p_z` states. The crystal field and hopping parameters for such a calculation can be obtained by post-processing DFT calculations. We will use values for NiO from [1]_. If you use values from a paper the relevant references should, of course, be cited. .. GENERATED FROM PYTHON SOURCE LINES 42-46 .. code-block:: Python import edrixs import numpy as np import matplotlib.pyplot as plt .. GENERATED FROM PYTHON SOURCE LINES 47-55 Number of electrons ------------------------------------------------------------------------------ We use a nominal Ni d8 impurity and a full bath of ten spin-orbitals. The bath orbitals are ligand combinations with d-like symmetry, not a second correlated atomic d shell. :func:`~edrixs.models.model_siam_2d1p` fixes one such bath and a p core. It infers 18 initial valence electrons from nd=8. Hybridization redistributes these electrons while conserving their total. All model energies and hoppings below are in eV. .. GENERATED FROM PYTHON SOURCE LINES 55-60 .. code-block:: Python nd = 8 # Fixed model dimensions, also used by the following analysis examples. norb_d = 10 nbath = 1 .. GENERATED FROM PYTHON SOURCE LINES 61-67 Coulomb interactions ------------------------------------------------------------------------------ The atomic Coulomb interactions are usually initialized based on Hartree-Fock calculations from, for example, `Cowan's code `_. edrixs has a database of these. .. GENERATED FROM PYTHON SOURCE LINES 67-69 .. code-block:: Python info = edrixs.utils.get_atom_data('Ni', '3d', nd, edge='L3') .. GENERATED FROM PYTHON SOURCE LINES 70-74 The atomic values are typically scaled to account for screening in the solid. Here we use 80% scaling. Let's write these out in full, so that nothing is hidden. Values for :math:`U_{dd}` and :math:`U_{dp}` are those of Ref. [1]_ obtained by comparing theory and experiment [2]_ [3]_. .. GENERATED FROM PYTHON SOURCE LINES 74-90 .. code-block:: Python scale_dd = 0.8 F2_dd = info['slater_i'][1][1] * scale_dd F4_dd = info['slater_i'][2][1] * scale_dd U_dd = 7.3 F0_dd = U_dd + edrixs.get_F0('d', F2_dd, F4_dd) scale_dp = 0.8 F2_dp = info['slater_n'][4][1] * scale_dp G1_dp = info['slater_n'][5][1] * scale_dp G3_dp = info['slater_n'][6][1] * scale_dp U_dp = 8.5 F0_dp = U_dp + edrixs.get_F0('dp', G1_dp, G3_dp) slater = ([F0_dd, F2_dd, F4_dd], # initial [F0_dd, F2_dd, F4_dd, F0_dp, F2_dp, G1_dp, G3_dp]) # with core hole .. GENERATED FROM PYTHON SOURCE LINES 91-98 Charge-transfer energy ------------------------------------------------------------------------------ Delta is the energy cost of transferring an electron from the ligand bath to the impurity: :math:`\Delta = E(d^{n_d+1}\underline{L}) - E(d^{n_d})`. This definition uses configuration-average energies without crystal field, hybridization, or multipolar Coulomb interactions. It is not the bare one-electron separation between the impurity and bath centers. .. GENERATED FROM PYTHON SOURCE LINES 98-100 .. code-block:: Python Delta = 4.7 .. GENERATED FROM PYTHON SOURCE LINES 101-109 Orbital energies and hybridization ------------------------------------------------------------------------------ Supply five real-harmonic orbital energies in the order (dz2, dzx, dzy, dx2-y2, dxy). Each value applies to both spins. The wrapper subtracts the mean of each set before adding its CT-derived center. Thus Delta controls the shell alignment independently of any common offset in these input energies. For cubic symmetry the two eg orbitals lie at +0.6*10Dq and the three t2g orbitals at -0.4*10Dq. .. GENERATED FROM PYTHON SOURCE LINES 109-114 .. code-block:: Python ten_dq = 0.56 impurity_levels = ten_dq * np.array([0.6, -0.4, -0.4, 0.6, -0.4]) ten_dq_bath = 1.44 bath_levels = ten_dq_bath * np.array([0.6, -0.4, -0.4, 0.6, -0.4]) .. GENERATED FROM PYTHON SOURCE LINES 115-118 Each hopping connects matching impurity and bath orbitals, with the same amplitude for both spins and both states. We use the eg and t2g values from Ref. [1]_. The wrapper handles spin duplication and basis conversion. .. GENERATED FROM PYTHON SOURCE LINES 118-122 .. code-block:: Python Veg = 2.06 Vt2g = 1.21 hyb = [Veg, Vt2g, Vt2g, Veg, Vt2g] .. GENERATED FROM PYTHON SOURCE LINES 123-129 Spin-orbit coupling ------------------------------------------------------------------------------ v_soc contains the initial and intermediate impurity SOC constants. We keep the same impurity SOC in both states to preserve this example's original parameterization. To use the separate atomic core-hole value instead, pass v_soc=(zeta_d_i, zeta_d_n). The p-core SOC is supplied separately as c_soc. .. GENERATED FROM PYTHON SOURCE LINES 129-134 .. code-block:: Python zeta_d_i = info['v_soc_i'][0] zeta_d_n = info['v_soc_n'][0] v_soc = (zeta_d_i, zeta_d_i) c_soc = info['c_soc'] .. GENERATED FROM PYTHON SOURCE LINES 135-137 We now need to define the parameters describing the XAS. X-ray polarization can be linear, circular or isotropic (appropriate for a powder). .. GENERATED FROM PYTHON SOURCE LINES 137-138 .. code-block:: Python poltype_xas = [('isotropic', 0)] .. GENERATED FROM PYTHON SOURCE LINES 139-141 edrixs uses the temperature in Kelvin to work out the population of the low-lying states via a Boltzmann distribution. .. GENERATED FROM PYTHON SOURCE LINES 141-142 .. code-block:: Python temperature = 300 .. GENERATED FROM PYTHON SOURCE LINES 143-144 The x-ray beam is specified by the incident angle and azimuthal angle in radians .. GENERATED FROM PYTHON SOURCE LINES 144-146 .. code-block:: Python thin = 0 / 180.0 * np.pi phi = 0.0 .. GENERATED FROM PYTHON SOURCE LINES 147-150 these are with respect to the crystal field :math:`z` and :math:`x` axes written above. (That is, unless you specify the :code:`loc_axis` parameter described in the :code:`edrixs.model_siam_2d1p` function documentation.) .. GENERATED FROM PYTHON SOURCE LINES 152-156 om_shift aligns the calculated XAS with the experimental Ni L edge. The wrapper combines this shift with its CT-derived core energy E_p through c_level = -om_shift - 5*E_p. Increasing om_shift raises the transition energies by the same amount. We center the photon-energy grid on this value. .. GENERATED FROM PYTHON SOURCE LINES 156-159 .. code-block:: Python om_shift = 857.6 ominc_xas = om_shift + np.linspace(-15, 25, 1000) .. GENERATED FROM PYTHON SOURCE LINES 160-164 The core-hole lifetime broadening is a half-width at half-maximum. You can either pass a constant value or an array the same size as :code:`ominc_xas` with varying values to simulate, for example, different state lifetimes for higher energy states. .. GENERATED FROM PYTHON SOURCE LINES 164-166 .. code-block:: Python gamma_c = np.full(ominc_xas.shape, 0.48/2) .. GENERATED FROM PYTHON SOURCE LINES 167-176 Magnetic field is a three-component vector in eV specified with respect to the same local axis as the x-ray beam. :code:`on_which = 'both'` applies the operator to the total spin plus orbital angular momentum, as is appropriate for a physical external magnetic field. Passing :code:`on_which = 'spin'` instead applies it to spin only, which is a convenient way to impose a magnetic order direction on the sample. The Bohr magneton :math:`\mu_B = 5.7883818012\times 10^{-5}` eV/T is useful for converting a physical field strength. Here we mimic magnetic order with an exchange energy of :math:`6 \times 0.027` eV directed along :math:`[112]`. .. GENERATED FROM PYTHON SOURCE LINES 176-180 .. code-block:: Python exchange = 6 * 0.027 ext_B = exchange / (2 * np.sqrt(6)) * np.array([1.0, 1.0, 2.0]) on_which = 'spin' .. GENERATED FROM PYTHON SOURCE LINES 181-194 Build the model ------------------------------------------------------------------------------ :func:`~edrixs.models.model_siam_2d1p` constructs the orbital-space model from the parameters above. It builds the one-body matrices, Coulomb tensors, and Fock-basis metadata; diagonalization remains a separate step. The returned i quantities describe initial/final states without a core hole, while the n quantities describe the intermediate state with a core hole. Both one-body matrices have shape (26, 26), and both Coulomb tensors include core orbitals. The initial basis is ((20, 18), (6, 6)); the occupancy nd+10 counts only impurity and bath electrons. Initial core interactions are active when supplied. trans_mat holds the Cartesian dipole matrices. General bath or hopping matrices can instead be supplied through :func:`~edrixs.models.model_siam`. .. GENERATED FROM PYTHON SOURCE LINES 194-202 .. code-block:: Python out = edrixs.model_siam_2d1p( slater=slater, nd=nd, Delta=Delta, impurity_levels=impurity_levels, bath_levels=bath_levels, hyb=hyb, v_soc=v_soc, c_soc=c_soc, om_shift=om_shift, ext_B=ext_B, on_which=on_which, ) emat_i, umat_i, basis_i, emat_n, umat_n, basis_n, trans_mat, shift = out .. GENERATED FROM PYTHON SOURCE LINES 203-216 Diagonalization ------------------------------------------------------------------------------ :func:`~edrixs.solvers.get_ops` converts these backend-independent ingredients into many-body initial/final and intermediate Hamiltonians, plus the dipole operators that map the initial Fock space to the intermediate one. Here we select the PETSc backend, which stores the Hamiltonians as distributed sparse matrices and uses SLEPc to extract the lowest eigenpairs. This scales to the larger Hilbert spaces typical of Anderson impurity models and runs in parallel if the script is launched with:: mpirun -n python example_03_AIM_XAS.py Running it as a plain :code:`python` script also works, it is just slower. .. GENERATED FROM PYTHON SOURCE LINES 216-222 .. code-block:: Python backend = 'petsc' hmat_i, hmat_n, trans_ops = edrixs.get_ops( emat_i, umat_i, basis_i, emat_n, umat_n, basis_n, trans_mat, backend=backend, ) .. GENERATED FROM PYTHON SOURCE LINES 223-226 :func:`~edrixs.solvers.ed` obtains the retained low-energy eigenpairs of the Hamiltonian without a core hole. Here :code:`num_evals=3` states are thermally populated at the temperature of interest. .. GENERATED FROM PYTHON SOURCE LINES 226-228 .. code-block:: Python eval_i, evec_i = edrixs.ed(hmat_i, shift=shift, num_evals=3) .. GENERATED FROM PYTHON SOURCE LINES 229-237 Compute XAS ------------------------------------------------------------------------------ The spectrum is built by applying the dipole operators to the thermally populated initial states and propagating in the intermediate-state Hamiltonian. EDRIXS weights the retained eigenstates by their Boltzmann factors at :code:`temperature`. Because our model includes hybridization, the spectrum captures charge-transfer processes in which electrons move between the O bath and the Ni impurity. .. GENERATED FROM PYTHON SOURCE LINES 237-243 .. code-block:: Python xas = edrixs.xas( eval_i, evec_i, hmat_n, trans_ops, ominc_xas, gamma_c=gamma_c, thin=thin, phi=phi, pol_type=poltype_xas, temperature=temperature, ) .. GENERATED FROM PYTHON SOURCE LINES 244-246 Let's plot the data and save it just in case. The returned array has shape :code:`(len(ominc_xas), len(poltype_xas))`. .. GENERATED FROM PYTHON SOURCE LINES 246-257 .. code-block:: Python if __name__ == "__main__": fig, ax = plt.subplots() ax.plot(ominc_xas, xas[:, 0]) ax.set_xlabel('Energy (eV)') ax.set_ylabel('XAS intensity') ax.set_title('Anderson impurity model for NiO') plt.show() np.savetxt('xas.dat', np.column_stack((ominc_xas, xas))) .. image-sg:: /auto_examples/images/sphx_glr_example_03_AIM_XAS_001.png :alt: Anderson impurity model for NiO :srcset: /auto_examples/images/sphx_glr_example_03_AIM_XAS_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 258-266 .. rubric:: Footnotes .. [1] Maurits Haverkort et al `Phys. Rev. B 85, 165113 (2012) `_. .. [2] A. E. Bocquet et al., `Phys. Rev. B 53, 1161 (1996) `_. .. [3] Arata Tanaka, and Takeo Jo, `J. Phys. Soc. Jpn. 63, 2788-2807(1994) `_. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.221 seconds) .. _sphx_glr_download_auto_examples_example_03_AIM_XAS.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: example_03_AIM_XAS.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: example_03_AIM_XAS.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: example_03_AIM_XAS.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_