{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# useful to autoreload the module without restarting the kernel\n", "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from mppi import Parsers as P\n", "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Tutorial of the PwParser class" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This tutorial describes the usage of the class PwParser of mppi used to extract information for the XML output file data-file-schema produced\n", "by pw." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parse of a output file of Silicon " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Follow the tutorial for the QeCalculator to produce the xml file used by the PwParser.__\n", "\n", "The class is initialized by specifying the name of the xml file including its relative path " ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Parse file : QeCalculator_test/ecut_50.save/data-file-schema.xml\n" ] } ], "source": [ "results = P.PwParser('QeCalculator_test/ecut_50.save/data-file-schema.xml')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When the object is initialized several attributes are set, for instance" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'Hartree atomic units'" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results.units" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n", "{'Si': ['2.808600000000000e1', 'Si.pbe-mt_fhi.UPF']}\n", "[['Si', [-1.2875, 1.2875, 1.2875]], ['Si', [1.2875, -1.2875, -1.2875]]]\n", "4\n", "32\n", "2\n" ] } ], "source": [ "print(results.natoms)\n", "print(results.atomic_species)\n", "print(results.atomic_positions)\n", "print(results.nbands)\n", "print(results.nkpoints)\n", "print(results.spin_degen)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can extract some lattice-related properties. For instance" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10.3\n", "[-5.15 0. 5.15] [0. 5.15 5.15] [-5.15 5.15 0. ]\n", "273.1817500000001\n" ] } ], "source": [ "print(results.alat) # the lattice parameter in a.u.\n", "lat = results.lattice # the array with the lattice vectors\n", "a1,a2,a3 = lat\n", "print(a1,a2,a3)\n", "print(results.eval_lattice_volume()) # lattice volume in a.u." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can check that, since the lattice is fcc the volume is $a_{lat}^3/4$" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "273.1817500000001" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results.alat**3/4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we need the lattice vectors in units of the lattice constant the `get_lattice` method can be used" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([[-0.5, 0. , 0.5],\n", " [ 0. , 0.5, 0.5],\n", " [-0.5, 0.5, 0. ]])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results.get_lattice(rescale=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also compute the vectors of the reciprocal lattice" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-1. -1. 1.] [1. 1. 1.] [-1. 1. -1.]\n" ] } ], "source": [ "rec_lat = results.get_reciprocal_lattice(rescale=True)\n", "b1,b2,b3 = rec_lat\n", "print(b1,b2,b3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We use the tools of the `ParsersUtils` module to compute the lattice volume" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3.9999999999999987" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "P.ParsersUtils.eval_lattice_volume(rec_lat)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0.9080043357303277" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "(2*np.pi)**3/results.eval_lattice_volume()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We check that if rescale=False, the volume of the reciprocal lattice is $(2\\pi)^3/vol_{lat}$. Instead, if the option rescale = True\n", "is chosen the volume of the reciprocal lattice is 4, as expected." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can access to the lattice symmetries" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "number of symmetries 48\n" ] }, { "data": { "text/plain": [ "array([[ 0., 0., 1.],\n", " [-1., -1., -1.],\n", " [ 1., 0., 0.]])" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "syms = results.syms\n", "print('number of symmetries',len(syms))\n", "syms[13]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can print the ks energies and weight for each kpoint" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0. 0. 0.] [-0.21239769 0.2248015 0.2248019 0.2248019 ] [0.00925926]\n", "[-0.16666667 0.16666667 -0.16666667] [-0.19923027 0.13749243 0.20843608 0.2084364 ] [0.05555556]\n", "[-0.33333333 0.33333333 -0.33333333] [-0.16224325 0.02984914 0.18835302 0.18835333] [0.05555556]\n", "[ 0.5 -0.5 0.5] [-0.12761605 -0.0295912 0.1810951 0.18109542] [0.02777778]\n", "[0. 0.33333333 0. ] [-0.19474764 0.14929523 0.18151447 0.18151464] [0.05555556]\n", "[-0.16666667 0.5 -0.16666667] [-0.16503928 0.06221564 0.15212893 0.16133873] [0.11111111]\n", "[ 0.66666667 -0.33333333 0.66666667] [-0.12174836 -0.01658335 0.12355478 0.16017609] [0.11111111]\n", "[ 0.5 -0.16666667 0.5 ] [-0.1357136 0.00516689 0.11382729 0.17756576] [0.11111111]\n", "[3.33333333e-01 2.77555756e-17 3.33333333e-01] [-0.17779262 0.08837439 0.13721986 0.20417699] [0.05555556]\n", "[0. 0.66666667 0. ] [-0.14298339 0.04081044 0.13688804 0.13688817] [0.05555556]\n", "[ 0.83333333 -0.16666667 0.83333333] [-0.10062076 -0.01579602 0.0928995 0.13189133] [0.11111111]\n", "[ 6.66666667e-01 -5.55111512e-17 6.66666667e-01] [-0.09359008 -0.02315423 0.06458065 0.14797813] [0.05555556]\n", "[ 0. -1. 0.] [-0.06137332 -0.06137309 0.12102867 0.12102879] [0.02777778]\n", "[ 0.66666667 -0.33333333 1. ] [-0.12899013 0.01785089 0.09513332 0.14145473] [0.11111111]\n", "[ 0.5 -0.16666667 0.83333333] [-0.09323708 -0.02570101 0.07904937 0.12455705] [0.11111111]\n", "[-0.33333333 -1. 0. ] [-0.05709944 -0.05709919 0.09247379 0.09247395] [0.11111111]\n", "[-0.16666667 0.16666667 0.16666667] [-0.19923026 0.13749218 0.20843636 0.20843636] [0.01851852]\n", "[-0.33333333 0.33333333 0.33333333] [-0.16224319 0.02984888 0.18835326 0.18835326] [0.01851852]\n", "[ 0.5 -0.5 -0.5] [-0.12761587 -0.02959158 0.18109533 0.18109533] [0.00925926]\n", "[ 0.16666667 -0.16666667 0.5 ] [-0.16503929 0.06221573 0.15212865 0.16133889] [0.05555556]\n", "[-0.16666667 0.16666667 0.5 ] [-0.16503926 0.06221543 0.15212897 0.16133886] [0.05555556]\n", "[-0.66666667 0.66666667 -0.33333333] [-0.12174836 -0.01658332 0.12355456 0.16017627] [0.05555556]\n", "[ 0.66666667 -0.66666667 -0.33333333] [-0.12174821 -0.01658369 0.12355481 0.16017623] [0.05555556]\n", "[-0.5 0.5 -0.16666667] [-0.13571357 0.00516682 0.11382715 0.17756596] [0.05555556]\n", "[ 0.5 -0.5 -0.16666667] [-0.1357135 0.00516657 0.11382734 0.17756593] [0.05555556]\n", "[-0.33333333 0.33333333 0. ] [-0.1777926 0.08837415 0.13721989 0.20417721] [0.05555556]\n", "[-0.83333333 0.83333333 -0.16666667] [-0.10062077 -0.01579597 0.09289929 0.13189146] [0.05555556]\n", "[ 0.83333333 -0.83333333 -0.16666667] [-0.10062068 -0.01579618 0.09289944 0.13189145] [0.05555556]\n", "[-0.66666667 0.66666667 0. ] [-0.09358994 -0.02315446 0.06458057 0.14797828] [0.05555556]\n", "[-0.66666667 1. -0.33333333] [-0.12899018 0.0178511 0.09513332 0.14145455] [0.11111111]\n", "[0.5 0.83333333 0.16666667] [-0.09323712 -0.02570097 0.07904955 0.12455686] [0.05555556]\n", "[ 0.5 -0.83333333 -0.16666667] [-0.09323691 -0.02570134 0.07904948 0.12455708] [0.05555556]\n" ] } ], "source": [ "for k,e,w in zip(results.kpoints,results.evals,results.weights):\n", " print(k,e,w)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can convert direct lattice quantities, like the atomic position, in crystal coordinates.\n", "For instance" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([-0.125, -0.125, -0.125])" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "atom1 = np.array([0.125,-0.125,-0.125]) # in units of alat\n", "P.ParsersUtils.convert_to_crystal(results.get_lattice(rescale=True),atom1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The k points can be expressed in crystal coordinates, _i.e._ in terms of the basis vector of the reciprocal lattice.\n", "\n", "For instance we compute the first 10 k points in these coordinates" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[array([0., 0., 0.]),\n", " array([0. , 0. , 0.16666667]),\n", " array([0. , 0. , 0.33333333]),\n", " array([ 0. , 0. , -0.5]),\n", " array([0. , 0.16666667, 0.16666667]),\n", " array([0. , 0.16666667, 0.33333333]),\n", " array([ 0. , 0.16666667, -0.5 ]),\n", " array([ 0. , 0.16666667, -0.33333333]),\n", " array([ 0. , 0.16666667, -0.16666667]),\n", " array([0. , 0.33333333, 0.33333333])]" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rec_lat = results.get_reciprocal_lattice(rescale=True)\n", "kpoints_crystal = []\n", "for k in results.kpoints[:10]:\n", " kpoints_crystal.append(P.ParsersUtils.convert_to_crystal(rec_lat,k))\n", "kpoints_crystal" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can check in the log of QuantumESPRESSO that these are the k points in crystal coordinates." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also perform the inverse procedure, for instance" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0. 0. 0.]\n", "[-0.16666667 0.16666667 -0.16666667]\n", "[-0.33333333 0.33333333 -0.33333333]\n", "[ 0.5 -0.5 0.5]\n", "[0. 0.33333333 0. ]\n", "[-0.16666667 0.5 -0.16666667]\n", "[ 0.66666667 -0.33333333 0.66666667]\n", "[ 0.5 -0.16666667 0.5 ]\n", "[0.33333333 0. 0.33333333]\n", "[0. 0.66666667 0. ]\n" ] } ], "source": [ "for k in kpoints_crystal:\n", " print(P.ParsersUtils.convert_to_cartesian(rec_lat,k))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are also several get methods, for instance" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "6.117171271888534" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results.get_fermi()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The method get_evals return an array with the ks energies for each kpoint. The energies are expressed in eV and the \n", "energy of VBM is used as reference. A gap, both direct or indirect, can be set. In this case the energies of the empty ks states is\n", "shifted. This procedure __does not__ update the occupation levels of the empty states" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "There are no empty bands. No energy shift has been applied\n" ] }, { "data": { "text/plain": [ "array([-1.18968067e+01, -1.08435998e-05, -6.32798614e-09, 0.00000000e+00])" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results.get_evals(set_gap=1.2)[0]" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "There are no empty states. Gap cannot be computed.\n" ] } ], "source": [ "results.get_gap()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We test the PwParser using a nscf output file, in this case empty bands are present and the gap can be computed" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Parse file : QeCalculator_test/bands_8.save/data-file-schema.xml\n" ] } ], "source": [ "result_nscf = P.PwParser('QeCalculator_test/bands_8.save/data-file-schema.xml')" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1., 1., 1., 1., 0., 0., 0., 0.])" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result_nscf.occupations[0]" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Indirect gap system\n", "===================\n", "Gap : 0.7360305350920111 eV\n", "Direct gap : 2.5651597869383274 eV\n" ] }, { "data": { "text/plain": [ "{'gap': 0.7360305350920111,\n", " 'direct_gap': 2.5651597869383274,\n", " 'position_cbm': 12,\n", " 'positon_vbm': 0}" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result_nscf.get_gap()" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Apply a scissor of 0.43484021306167264 eV\n" ] }, { "data": { "text/plain": [ "array([-1.18968473e+01, -3.77496830e-06, -2.75945489e-10, 0.00000000e+00,\n", " 3.00000000e+00, 3.00000000e+00, 3.00000201e+00, 3.58149154e+00])" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result_nscf.get_evals(set_direct_gap=3.0)[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "we see that in this case the energy of the 5-th states has been shift to 3 eV to implement the set_direct_gap requirement. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is also possible to add an explicit scissor to shift the empty bands" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Apply a scissor of 1.0 eV\n" ] }, { "data": { "text/plain": [ "array([-1.18968473e+01, -3.77496830e-06, -2.75945489e-10, 0.00000000e+00,\n", " 3.56515979e+00, 3.56515979e+00, 3.56516180e+00, 4.14665133e+00])" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result_nscf.get_evals(set_scissor=1.)[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We compute the transition energies from the full to empty bands. Here we show the transition\n", "for the first k point" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([14.89684725, 14.89684725, 14.89684927, 15.47833879, 3.00000377,\n", " 3.00000377, 3.00000579, 3.58149531, 3. , 3. ,\n", " 3.00000201, 3.58149154, 3. , 3. , 3.00000201,\n", " 3.58149154])" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result_nscf.get_transitions(set_direct_gap=3.0)[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parse of a Graphene output file" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "__Run the Analysis_BandStructure notebook to produce the xml file used by the PwParser.__\n", "\n", "We parse a graphene output file to test if systems without a gap are correctly parsed." ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Parse file : Pw_bands/graphene_nscf.save/data-file-schema.xml\n" ] } ], "source": [ "results_gra = P.PwParser('Pw_bands/graphene_nscf.save/data-file-schema.xml')" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'smearing'" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results_gra.occupations_kind" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1.00000000e+00, 1.00000000e+00, 1.00000000e+00, 1.00000000e+00,\n", " 4.22181265e-29, 6.89778699e-37, 1.76721673e-41, 1.28104982e-57])" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results_gra.occupations[0]" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1. , 1. , 1. , 0.5, 0.5, 0. , 0. , 0. ])" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results_gra.occupations[18] #the position of K" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Direct gap system\n", "=================\n", "Gap : 2.715685454290906e-10 eV\n" ] }, { "data": { "text/plain": [ "{'gap': 2.715685454290906e-10,\n", " 'direct_gap': 2.715685454290906e-10,\n", " 'position_cbm': 18,\n", " 'positon_vbm': 18}" ] }, "execution_count": 68, "metadata": {}, "output_type": "execute_result" } ], "source": [ "results_gra.get_gap()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.6" } }, "nbformat": 4, "nbformat_minor": 4 }