.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "master-tutorial/1_python-library/plot_7_wulfric.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_master-tutorial_1_python-library_plot_7_wulfric.py: (extra) Wulfric *************** .. include:: ../../exercises/7.inc For the upcoming tutorials we need to be able to generate a set of k-points. In particular, a set of k-points for the k-path between high-symmetry points. There is a number of ways to do so and a number of packages out there that can deal with such a task. Magnopy use one of them, |wulfric|_, as a dependency for k-points, symmetry analysis (powered by |spglib|_) and visualization (powered by |plotly|_). That is why in the tutorials we will use |wulfric|_ for automatic generation of k-points. In this tutorial we briefly introduce it. It is not necessary to use |wulfric|_, please feel free to skip this tutorial if you have other ways to generate k-points. .. GENERATED FROM PYTHON SOURCE LINES 17-41 .. code-block:: Python import numpy as np import wulfric import matplotlib.pyplot as plt # Get a cubic cell with a = 4 cell = 4 * np.eye(3) # Eight atoms: four will be magnetic, and four will not atoms = dict( names=["Fe1", "Fe2", "Fe3", "Fe4", "O1", "O2", "O3", "O4"], positions=[ [0.0, 0.0, 0.0], [0.5, 0.5, 0.0], [0.0, 0.5, 0.5], [0.5, 0.0, 0.5], [0.5, 0.5, 0.5], [0.5, 0.0, 0.0], [0.0, 0.5, 0.0], [0.0, 0.0, 0.5], ], spins=[2.5, 2.5, 2.5, 2.5, None, None, None, None], g_factors=[2, 2, 2, 2, None, None, None, None], ) .. GENERATED FROM PYTHON SOURCE LINES 42-55 Getting symmetry information ============================ Many of wulfric's functions accept optional parameter called ``spglib_data``. Each of them behave in the same way whether such parameter is given or not (if not given, it is created internally). However, if you plan to call multiple wulfric functions that need ``spglib_data``, it is more efficient to create it once and pass it to those functions. You can skip this section if you do not plan to do so. .. hint:: Create an ``spglib_data`` after you finished modifying the crystal structure. If you modify the crystal structure, then you need to re-create ``spglib_data``. .. GENERATED FROM PYTHON SOURCE LINES 56-59 .. code-block:: Python spglib_data = wulfric.get_spglib_data(cell=cell, atoms=atoms, spglib_symprec=1e-5) .. GENERATED FROM PYTHON SOURCE LINES 60-73 .. note:: * ``spglib_symprec`` is a tolerance parameter for the space group search that is directly passed to |spglib|_, see its docs for more information. Default value ``1e-5`` is usually good enough. You can try to increase it if your crystal structure is slightly distorted and computed space group is not the one you would expect. * |spglib|_ decides which atoms in the unit cell are equivalent based on ``spglib_types`` - a list of positive, non-zero integers. |wulfric|_ guesses ``spglib_types`` for you, based on the ``atoms`` dictionary. See :py:func:`wulfric.get_spglib_types` to read how this guess is done. Here are the ``spglib_types``, that were guessed by wulfric: .. GENERATED FROM PYTHON SOURCE LINES 74-77 .. code-block:: Python print(spglib_data.original_types) .. rst-class:: sphx-glr-script-out .. code-block:: none [1, 1, 1, 1, 2, 2, 2, 2] .. GENERATED FROM PYTHON SOURCE LINES 78-80 If you want to control how ``spglib_types`` are defined, then you can add them directly to ``atoms`` .. GENERATED FROM PYTHON SOURCE LINES 81-84 .. code-block:: Python atoms["spglib_types"] = [1, 1, 1, 1, 2, 2, 2, 2] .. GENERATED FROM PYTHON SOURCE LINES 85-91 Symmetry information ==================== A number of properties about the underlying crystal can be displayed now See :py:func:`wulfric.get_spglib_data` for full list of available keys. .. GENERATED FROM PYTHON SOURCE LINES 92-97 .. code-block:: Python print(f"Space group: {spglib_data.space_group_number}") print(f"Bravais lattice: {spglib_data.crystal_family + spglib_data.centring_type}") .. rst-class:: sphx-glr-script-out .. code-block:: none Space group: 225 Bravais lattice: cF .. GENERATED FROM PYTHON SOURCE LINES 98-104 |wulfric|_ supports two conventions for the high-symmetry k-points: by Hinuma, Pizzi, Kumagai, Oba, Tanaka (HPKOT) [1]_ and by Setyawan and Curtarolo (SC) [2]_. Magnopy defaults to |wulfric-HPKOT|_ internally. HPKOT convention ---------------- .. GENERATED FROM PYTHON SOURCE LINES 105-121 .. code-block:: Python hpkot_ebls = wulfric.crystal.hpkot_get_extended_bl_symbol( cell=cell, atoms=atoms, spglib_data=spglib_data ) print(f"Extended Bravais lattice symbol according to HPKOT: {hpkot_ebls}") hpkot_kpath, hpkot_hs_points = wulfric.kpoints.get_path_and_points( cell=cell, atoms=atoms, spglib_data=spglib_data, convention="HPKOT" ) print(f"Recommended k-path according to HPKOT: {hpkot_kpath}") # hs_points is a dictionary: {name : coordinate, ...} print("Pre-defined high symmetry points according to HPKOT:") for name, rel_pos in hpkot_hs_points.items(): print(f"* {name:<7} at {rel_pos[0]:>8.5f} {rel_pos[0]:>8.5f} {rel_pos[0]:>8.5f}") .. rst-class:: sphx-glr-script-out .. code-block:: none Extended Bravais lattice symbol according to HPKOT: cF2 Recommended k-path according to HPKOT: GAMMA-X-U|K-GAMMA-L-W-X Pre-defined high symmetry points according to HPKOT: * GAMMA at 0.00000 0.00000 0.00000 * X at 0.00000 0.00000 0.00000 * L at 0.50000 0.50000 0.50000 * W at 0.50000 0.50000 0.50000 * W2 at 0.00000 0.00000 0.00000 * K at 0.75000 0.75000 0.75000 * U at 0.25000 0.25000 0.25000 .. GENERATED FROM PYTHON SOURCE LINES 122-124 SC convention ------------- .. GENERATED FROM PYTHON SOURCE LINES 125-140 .. code-block:: Python sc_variation = wulfric.crystal.sc_get_variation( cell=cell, atoms=atoms, spglib_data=spglib_data ) print(f"Bravais lattice variation according to SC: {sc_variation}") sc_kpath, sc_hs_points = wulfric.kpoints.get_path_and_points( cell=cell, atoms=atoms, spglib_data=spglib_data, convention="SC" ) print(f"Recommended k-path according to SC: {sc_kpath}") # hs_points is a dictionary: {name : coordinate, ...} print("Pre-defined high symmetry points according to SC:") for name, rel_pos in sc_hs_points.items(): print(f"* {name:<7} at {rel_pos[0]:>8.5f} {rel_pos[0]:>8.5f} {rel_pos[0]:>8.5f}") .. rst-class:: sphx-glr-script-out .. code-block:: none Bravais lattice variation according to SC: FCC Recommended k-path according to SC: GAMMA-X-W-K-GAMMA-L-U-W-L-K|U-X Pre-defined high symmetry points according to SC: * GAMMA at 0.00000 0.00000 0.00000 * K at 0.75000 0.75000 0.75000 * L at 0.50000 0.50000 0.50000 * U at 0.25000 0.25000 0.25000 * W at 0.50000 0.50000 0.50000 * X at 0.00000 0.00000 0.00000 .. GENERATED FROM PYTHON SOURCE LINES 141-182 Coordinates of the high-symmetry points are relative. Read further to find out what are they relative to. .. hint:: To get absolute coordinates of the high-symmetry points pass ``relative=False`` to :py:func:`wulfric.kpoints.get_path_and_points`. From this point we will use HPKOT convention. Cell, cell and cell =================== Please read |wulfric-which-cell|_ to understand the title of this section. We typically call ``spinham.cell`` "cell" or "unit cell" or "input cell" or "original cell". There is no implication on what kind of cell it can be. In fact, it can be a supercell or a primitive cell or a conventional cell or none of those. * Conventional cell Chosen cell for each space group, that can contain more than one lattice point. Depends on the convention. * Primitive cell Chosen cell for each space group, that contains exactly one lattice point. Depends on the convention. * Supercell A cell that contain several repetitions of the original cell. .. hint:: If ``spglib_types`` are not modified between cells in the supercell, then any supercell for an arbitrary given cell will have the same primitive and conventional cells. Here is a visualization (we use :py:class:`wulfric.PlotlyEngine`, but exactly the same figure can be done with :py:class:`magnopy.PlotlyEngine`). .. GENERATED FROM PYTHON SOURCE LINES 183-220 .. code-block:: Python conv_cell, conv_atoms = wulfric.crystal.get_conventional( cell=cell, atoms=atoms, spglib_data=spglib_data, convention="HPKOT" ) prim_cell, prim_atoms = wulfric.crystal.get_primitive( cell=cell, atoms=atoms, spglib_data=spglib_data, convention="HPKOT" ) pe = wulfric.PlotlyEngine(_sphinx_gallery_fix=True) pe.plot_cell(cell=cell, legend_label="Original cell", color="#000000") pe.plot_atoms( cell=cell, atoms=atoms, legend_label="Original atoms", colors=["#000000" for _ in atoms["names"]], ) pe.plot_cell(cell=conv_cell, legend_label="Conventional cell", color="#0057B7") pe.plot_atoms( cell=conv_cell, atoms=conv_atoms, legend_label="Conventional atoms", colors=["#0057B7" for _ in conv_atoms["names"]], ) pe.plot_cell(cell=prim_cell, legend_label="Primitive cell", color="#FFDD00") pe.plot_atoms( cell=prim_cell, atoms=prim_atoms, legend_label="Primitive atoms", colors=["#FFDD00" for _ in prim_atoms["names"]], ) pe.show(axes_visible=False, legend_position="left") .. raw:: html


.. GENERATED FROM PYTHON SOURCE LINES 221-227 .. note:: * In this example input cell is the conventional cell of the crystal. * In this example conventional and primitive cells are different. * Both statements from above are crystal-specific, convention-specific and depend on the choice of the input cell, even for the same crystal and convention. .. GENERATED FROM PYTHON SOURCE LINES 231-260 High-symmetry points and k-path =============================== Now we are ready to answer the question from above: what are relative coordinates of high symmetry points relative to? .. important:: * High symmetry k-points returned by |wulfric|_ are the high-symmetry points of the Brillouin zone of the **primitive cell** * Relative coordinates of high-symmetry points produced by |wulfric|_ are given in the basis of (relative to) the reciprocal cell of the **input cell** Please take a moment to think about those two statements. They have some subtle consequences, among which are the following * Wulfric always returns high-symmetry points and k-path appropriate to the symmetry of the given crystal. In other words, they are not defined by just the input cell alone. They can be different for the same cell, if it is paired with different set of atoms (or same set of atoms with different ``spglib_types``). * High-symmetry points and k-path will be the same for some given cell and all of its super-cells. The relative coordinates of the high-symmetry points will change from supercell to supercell, but absolute ones and names will remain the same. * If you want to obtain high symmetry points and k-path for any given cell alone, then use it with a "blank" set of atoms, i. e. ``atoms = dict(spglib_types = [1], positions=[[0, 0, 0]])`` We will illustrate those facts below. First, we introduce a convenient interface to the k-points that we will use in the later tutorials: :py:class:`wulfric.Kpoints` class. .. GENERATED FROM PYTHON SOURCE LINES 261-268 .. code-block:: Python kp = wulfric.Kpoints.from_crystal(cell=cell, atoms=atoms) # Coordinates of the high symmetry points ar relative to kp.rcell print(np.allclose(kp.rcell, wulfric.cell.get_reciprocal(cell=cell))) .. rst-class:: sphx-glr-script-out .. code-block:: none True .. GENERATED FROM PYTHON SOURCE LINES 269-280 .. note:: The simple call to the :py:func:`wulfric.Kpoints.from_crystal` can be improved. For example, * We could have passed ``convention="HPKOT"`` or ``convention="SC"`` to :py:func:`wulfric.Kpoints.from_crystal`. "HPKOT" is used by default. * We could have passed ``spglib_data=spglib_data`` to :py:func:`wulfric.Kpoints.from_crystal` to avoid recomputing it internally. Now we can visualize high-symmetry points and k-path. .. GENERATED FROM PYTHON SOURCE LINES 281-314 .. code-block:: Python kp_of_input_cell = wulfric.Kpoints.from_crystal( cell=cell, atoms=dict(spglib_types=[1], positions=[[0, 0, 0]]) ) pe = wulfric.PlotlyEngine(_sphinx_gallery_fix=True) pe.plot_kpoints( kp, color="#C8102E", legend_label="High-symmetry points (crystal-based)" ) pe.plot_kpath(kp, color="#C8102E", legend_label="Recommended k-path (crystal-based)") pe.plot_brillouin_zone( cell=prim_cell, color="#C8102E", legend_label="Brillouin zone of the primitive cell", ) pe.plot_kpoints( kp_of_input_cell, color="#003DA5", legend_label="High-symmetry points (cell-based)" ) pe.plot_kpath( kp_of_input_cell, color="#003DA5", legend_label="Recommended k-path (cell-based)" ) pe.plot_brillouin_zone( cell=cell, color="#003DA5", legend_label="Brillouin zone of the input cell", ) pe.show(axes_visible=False, legend_position="left") .. raw:: html


.. GENERATED FROM PYTHON SOURCE LINES 315-329 Using Kpoints class =================== Finally, after we explained how high-symmetry points and k-path are chosen by |wulfric|_, we give some tips on how to use :py:class:`wulfric.Kpoints` both for calculation and for plotting. For illustrative purposes we will create an instance of such class by hand. .. hint:: When you are working with an actual crystal structure, we recommend to use :py:func:`wulfric.Kpoints.from_crystal`, for example .. code-block:: python kp = wulfric.Kpoints.from_crystal(cell=spinham.cell, atoms=spinham.atoms) .. GENERATED FROM PYTHON SOURCE LINES 330-339 .. code-block:: Python kp = wulfric.Kpoints( rcell=np.eye(3), coordinates=[[0, 0, 0], [0, 0.5, 0], [0.5, 0.5, 0], [0.5, 0.5, 0.5]], names=["GAMMA", "X", "M", "R"], labels=[R"$\Gamma$", "X", "M", "R"], path="GAMMA-X-M-GAMMA-R-X|M-R", ) .. GENERATED FROM PYTHON SOURCE LINES 340-345 For calculation ---------------- :py:attr:`wulfric.Kpoints.n` controls how many kpoints are inserted between each pair (that connected by "-" in the k-path string) of high symmetry points. It defaults to 100, we change it to 10 for illustrative purposes .. GENERATED FROM PYTHON SOURCE LINES 346-349 .. code-block:: Python kp.n = 10 .. GENERATED FROM PYTHON SOURCE LINES 350-352 :py:attr:`wulfric.Kpoints.points` returns a list of k-points from the k-path with n points inserted in between high-symmetry points. Coordinates are absolute by default .. GENERATED FROM PYTHON SOURCE LINES 353-366 .. code-block:: Python for k_b1, k_b2, k_b3 in kp.points(relative=True): print(f"{k_b1:>8.5f} {k_b2:>8.5f} {k_b3:>8.5f}", end="") found_close = False for name in kp.hs_names: if np.allclose(kp.hs_coordinates[name], (k_b1, k_b2, k_b3)): found_close = True print(f" <- {name}") break if not found_close: print() .. rst-class:: sphx-glr-script-out .. code-block:: none 0.00000 0.00000 0.00000 <- GAMMA 0.00000 0.04545 0.00000 0.00000 0.09091 0.00000 0.00000 0.13636 0.00000 0.00000 0.18182 0.00000 0.00000 0.22727 0.00000 0.00000 0.27273 0.00000 0.00000 0.31818 0.00000 0.00000 0.36364 0.00000 0.00000 0.40909 0.00000 0.00000 0.45455 0.00000 0.00000 0.50000 0.00000 <- X 0.00000 0.50000 0.00000 <- X 0.04545 0.50000 0.00000 0.09091 0.50000 0.00000 0.13636 0.50000 0.00000 0.18182 0.50000 0.00000 0.22727 0.50000 0.00000 0.27273 0.50000 0.00000 0.31818 0.50000 0.00000 0.36364 0.50000 0.00000 0.40909 0.50000 0.00000 0.45455 0.50000 0.00000 0.50000 0.50000 0.00000 <- M 0.50000 0.50000 0.00000 <- M 0.45455 0.45455 0.00000 0.40909 0.40909 0.00000 0.36364 0.36364 0.00000 0.31818 0.31818 0.00000 0.27273 0.27273 0.00000 0.22727 0.22727 0.00000 0.18182 0.18182 0.00000 0.13636 0.13636 0.00000 0.09091 0.09091 0.00000 0.04545 0.04545 0.00000 0.00000 0.00000 0.00000 <- GAMMA 0.00000 0.00000 0.00000 <- GAMMA 0.04545 0.04545 0.04545 0.09091 0.09091 0.09091 0.13636 0.13636 0.13636 0.18182 0.18182 0.18182 0.22727 0.22727 0.22727 0.27273 0.27273 0.27273 0.31818 0.31818 0.31818 0.36364 0.36364 0.36364 0.40909 0.40909 0.40909 0.45455 0.45455 0.45455 0.50000 0.50000 0.50000 <- R 0.50000 0.50000 0.50000 <- R 0.45455 0.50000 0.45455 0.40909 0.50000 0.40909 0.36364 0.50000 0.36364 0.31818 0.50000 0.31818 0.27273 0.50000 0.27273 0.22727 0.50000 0.22727 0.18182 0.50000 0.18182 0.13636 0.50000 0.13636 0.09091 0.50000 0.09091 0.04545 0.50000 0.04545 0.00000 0.50000 0.00000 <- X 0.50000 0.50000 0.00000 <- M 0.50000 0.50000 0.04545 0.50000 0.50000 0.09091 0.50000 0.50000 0.13636 0.50000 0.50000 0.18182 0.50000 0.50000 0.22727 0.50000 0.50000 0.27273 0.50000 0.50000 0.31818 0.50000 0.50000 0.36364 0.50000 0.50000 0.40909 0.50000 0.50000 0.45455 0.50000 0.50000 0.50000 <- R .. GENERATED FROM PYTHON SOURCE LINES 367-372 For plotting ------------ :py:attr:`wulfric.Kpoints.flat_points` returns a list of flat indices that can be used in the band structure plots. Same length as in :py:attr:`wulfric.Kpoints.points`. .. GENERATED FROM PYTHON SOURCE LINES 373-388 .. code-block:: Python print(len(kp.points()) == len(kp.flat_points())) for flat_index, point in zip(kp.flat_points(), kp.points(relative=True)): print(f"{flat_index:>8.5f}", end="") found_close = False for name in kp.hs_names: if np.allclose(kp.hs_coordinates[name], point): found_close = True print(f" <- {name}") break if not found_close: print() .. rst-class:: sphx-glr-script-out .. code-block:: none True 0.00000 <- GAMMA 0.04545 0.09091 0.13636 0.18182 0.22727 0.27273 0.31818 0.36364 0.40909 0.45455 0.50000 <- X 0.50000 <- X 0.54545 0.59091 0.63636 0.68182 0.72727 0.77273 0.81818 0.86364 0.90909 0.95455 1.00000 <- M 1.00000 <- M 1.06428 1.12856 1.19285 1.25713 1.32141 1.38569 1.44998 1.51426 1.57854 1.64282 1.70711 <- GAMMA 1.70711 <- GAMMA 1.78584 1.86457 1.94330 2.02203 2.10075 2.17948 2.25821 2.33694 2.41567 2.49440 2.57313 <- R 2.57313 <- R 2.63741 2.70170 2.76598 2.83026 2.89454 2.95883 3.02311 3.08739 3.15167 3.21596 3.28024 <- X 3.28024 <- M 3.32569 3.37115 3.41660 3.46206 3.50751 3.55297 3.59842 3.64388 3.68933 3.73478 3.78024 <- R .. GENERATED FROM PYTHON SOURCE LINES 389-392 :py:attr:`wulfric.Kpoints.ticks` and :py:attr:`wulfric.Kpoints.labels` return positions and labels of the high-symmetry points. :py:attr:`wulfric.Kpoints.ticks` are on the same scale as :py:attr:`wulfric.Kpoints.flat_points` .. GENERATED FROM PYTHON SOURCE LINES 393-398 .. code-block:: Python for tick, label in zip(kp.ticks(), kp.labels): print(f"{tick:>8.5f} -> {label}") .. rst-class:: sphx-glr-script-out .. code-block:: none 0.00000 -> $\Gamma$ 0.50000 -> X 1.00000 -> M 1.70711 -> $\Gamma$ 2.57313 -> R 3.28024 -> X|M 3.78024 -> R .. GENERATED FROM PYTHON SOURCE LINES 399-403 Example ------- Here is an example of how those attributes can be used. .. GENERATED FROM PYTHON SOURCE LINES 404-429 .. code-block:: Python # Prepare some tricks a, b, c, _, _, _ = wulfric.cell.get_params(cell=wulfric.cell.get_reciprocal(kp.rcell)) # Use in calculations points = kp.points() data = ( 3 + np.cos(a * points[:, 0]) + np.cos(b * points[:, 1]) + np.cos(c * points[:, 2]) ) # Use in plotting fig, ax = plt.subplots() ax.plot(kp.flat_points(), data, lw=2, color="#98E534") ax.set_xticks(kp.ticks(), kp.labels, fontsize=15) ax.set_ylabel("Data", fontsize=15) ax.set_xlim(kp.ticks()[0], kp.ticks()[-1]) ax.set_ylim(0, None) ax.vlines(kp.ticks(), 0, 1, lw=0.5, color="grey", transform=ax.get_xaxis_transform()) fig.show() .. image-sg:: /master-tutorial/1_python-library/images/sphx_glr_plot_7_wulfric_001.png :alt: plot 7 wulfric :srcset: /master-tutorial/1_python-library/images/sphx_glr_plot_7_wulfric_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 430-439 References ========== .. [1] Hinuma, Y., Pizzi, G., Kumagai, Y., Oba, F. and Tanaka, I., 2017. Band structure diagram paths based on crystallography. Computational Materials Science, 128, pp.140-184. .. [2] Setyawan, W. and Curtarolo, S., 2010. High-throughput electronic band structure calculations: Challenges and tools. Computational materials science, 49(2), pp. 299-312. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.219 seconds) .. _sphx_glr_download_master-tutorial_1_python-library_plot_7_wulfric.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_7_wulfric.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_7_wulfric.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_7_wulfric.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_