Beispiel #1
0
    def read_doses(self):
        """
        Return a |AttrDict| with the DOSes available in the file. Empty dict if
        DOSes are not available.
        """
        if "gruns_nomega" not in self.rootgrp.dimensions:
            cprint("File `%s` does not contain ph-DOSes, returning empty dict" % self.path, "yellow")
            return {}

        # Read q-point sampling used to compute DOSes.
        qptrlatt = self.read_value("gruns_qptrlatt")
        shifts = self.read_value("gruns_shiftq")
        qsampling = KSamplingInfo.from_kptrlatt(qptrlatt, shifts, kptopt=1)

        frac_coords_ibz = self.read_value("gruns_qibz")
        weights = self.read_value("gruns_wtq")
        qpoints = IrredZone(self.structure.reciprocal_lattice, frac_coords_ibz,
                            weights=weights, names=None, ksampling=qsampling)

        # DOSes are in 1/Hartree.
        d = AttrDict(wmesh=self.read_value("gruns_omega_mesh") * abu.Ha_eV, qpoints=qpoints)

        for dos_name in _ALL_DOS_NAMES:
            dos_idos = self.read_value(dos_name)
            dos_idos[0] *= abu.eV_Ha  # Here we convert to eV. IDOS are not changed.
            d[dos_name] = dos_idos

        return d
Beispiel #2
0
def main():
    #import m_kpoints
    #from m_kpoints import m_kpoints  as mod
    #print(m_kpoints.__doc__)
    #v1 = np.zeros(3)
    #v2 = v1 + 1.0
    #print(v1, v2)

    #ans, g0 = mod.isamek(v1, v2)
    #print(ans,g0)

    from abipy.core.kpoints import IrredZone, kmesh_from_mpdivs

    filename = "/Users/gmatteo/Coding/abipy/abipy/data/runs/data_si_ebands/outdata/si_scf_GSR.nc"
    structure = Structure.from_file(filename)

    ibz = IrredZone.from_file(filename)
    #print(ibz)

    mpdivs = [8, 8, 8]
    shifts = [0.0, 0.0, 0.0]

    #tables = map_mesh2ibz(structure, mpdivs, shifts, ibz)

    bz = kmesh_from_mpdivs(mpdivs, shifts)

    ktab = slow_map_mesh2ibz(structure, bz, ibz.frac_coords)
Beispiel #3
0
    def test_irredzone_api(self):
        """Testing IrredZone API."""
        structure = abilab.Structure.as_structure(abidata.cif_file("si.cif"))

        ibz = IrredZone.from_ngkpt(structure, ngkpt=[4, 4, 4], shiftk=[0.0, 0.0, 0.0], verbose=2)
        repr(ibz); str(ibz)
        assert ibz.to_string(verbose=2)
        assert ibz.is_ibz
        assert len(ibz) == 8
        assert ibz.ksampling.kptopt == 1
        self.assert_equal(ibz.ksampling.mpdivs, [4, 4, 4])

        ibz = IrredZone.from_kppa(structure, kppa=1000, shiftk=[0.5, 0.5, 0.5], kptopt=1, verbose=1)
        assert ibz.is_ibz
        assert len(ibz) == 60
        self.assert_equal(ibz.ksampling.mpdivs, [8, 8, 8])
Beispiel #4
0
def main():
    #import m_kpoints
    #from m_kpoints import m_kpoints  as mod
    #print(m_kpoints.__doc__)
    #v1 = np.zeros(3)
    #v2 = v1 + 1.0
    #print(v1, v2)

    #ans, g0 = mod.isamek(v1, v2)
    #print(ans,g0)

    from abipy.core.kpoints import IrredZone, kmesh_from_mpdivs

    filename = "/Users/gmatteo/Coding/abipy/abipy/data/runs/data_si_ebands/outdata/si_scf_GSR.nc"
    structure = Structure.from_file(filename)

    ibz = IrredZone.from_file(filename)
    #print(ibz)

    mpdivs = [8, 8, 8]
    shifts = [0.0, 0.0, 0.0]

    #tables = map_mesh2ibz(structure, mpdivs, shifts, ibz)

    bz = kmesh_from_mpdivs(mpdivs, shifts)

    ktab = slow_map_mesh2ibz(structure, bz, ibz.frac_coords)
Beispiel #5
0
    def get_interpolated_ebands_plotter(self,
                                        vertices_names=None,
                                        knames=None,
                                        line_density=20,
                                        ngkpt=None,
                                        shiftk=(0, 0, 0),
                                        kpoints=None,
                                        **kwargs):
        """
        Args:
            vertices_names: Used to specify the k-path for the interpolated QP band structure
                It's a list of tuple, each tuple is of the form (kfrac_coords, kname) where
                kfrac_coords are the reduced coordinates of the k-point and kname is a string with the name of
                the k-point. Each point represents a vertex of the k-path. ``line_density`` defines
                the density of the sampling. If None, the k-path is automatically generated according
                to the point group of the system.
            knames: List of strings with the k-point labels defining the k-path. It has precedence over `vertices_names`.
            line_density: Number of points in the smallest segment of the k-path. Used with ``vertices_names``.
            ngkpt: Mesh divisions. Used if bands should be interpolated in the IBZ.
            shiftk: Shifts for k-meshs. Used with ngkpt.
            kpoints: |KpointList| object taken e.g from a previous ElectronBands.
                Has precedence over vertices_names and line_density.

        Return: |ElectronBandsPlotter| object.
        """
        diff_str = self.has_different_structures()
        if diff_str: cprint(diff_str, "yellow")

        # Need KpointList object (assume same structures in Robot)
        nc0 = self.abifiles[0]
        if kpoints is None:
            if ngkpt is not None:
                # IBZ sampling
                kpoints = IrredZone.from_ngkpt(nc0.structure,
                                               ngkpt,
                                               shiftk,
                                               kptopt=1,
                                               verbose=0)
            else:
                # K-Path
                if knames is not None:
                    kpoints = Kpath.from_names(nc0.structure,
                                               knames,
                                               line_density=line_density)
                else:
                    if vertices_names is None:
                        vertices_names = [(k.frac_coords, k.name)
                                          for k in nc0.structure.hsym_kpoints]
                    kpoints = Kpath.from_vertices_and_names(
                        nc0.structure,
                        vertices_names,
                        line_density=line_density)

        plotter = ElectronBandsPlotter()
        for label, abiwan in self.items():
            plotter.add_ebands(label,
                               abiwan.interpolate_ebands(kpoints=kpoints))

        return plotter
Beispiel #6
0
    def interpolate_ebands(self, vertices_names=None, line_density=20, ngkpt=None, shiftk=(0, 0, 0), kpoints=None):
        """
        Build new |ElectronBands| object by interpolating the KS Hamiltonian with Wannier functions.
        Supports k-path via (vertices_names, line_density), IBZ mesh defined by ngkpt and shiftk
        or input list of kpoints.

        Args:
            vertices_names: Used to specify the k-path for the interpolated QP band structure
                List of tuple, each tuple is of the form (kfrac_coords, kname) where
                kfrac_coords are the reduced coordinates of the k-point and kname is a string with the name of
                the k-point. Each point represents a vertex of the k-path. ``line_density`` defines
                the density of the sampling. If None, the k-path is automatically generated according
                to the point group of the system.
            line_density: Number of points in the smallest segment of the k-path. Used with ``vertices_names``.
            ngkpt: Mesh divisions. Used if bands should be interpolated in the IBZ.
            shiftk: Shifts for k-meshs. Used with ngkpt.
            kpoints: |KpointList| object taken e.g from a previous ElectronBands.
                Has precedence over vertices_names and line_density.

        Returns: |ElectronBands| object with Wannier-interpolated energies.
        """
        # Need KpointList object.
        if kpoints is None:
            if ngkpt is not None:
                # IBZ sampling
                kpoints = IrredZone.from_ngkpt(self.structure, ngkpt, shiftk, kptopt=1, verbose=0)
            else:
                # K-Path
                if vertices_names is None:
                    vertices_names = [(k.frac_coords, k.name) for k in self.structure.hsym_kpoints]
                kpoints = Kpath.from_vertices_and_names(self.structure, vertices_names, line_density=line_density)

        nk = len(kpoints)
        eigens = np.zeros((self.nsppol, nk, self.mwan))

        # Interpolate Hamiltonian for each kpoint and spin.
        start = time.time()
        write_warning = True
        for spin in range(self.nsppol):
            num_wan = self.nwan_spin[spin]
            for ik, kpt in enumerate(kpoints):
                oeigs = self.hwan.eval_sk(spin, kpt.frac_coords)
                eigens[spin, ik, :num_wan] = oeigs
                if num_wan < self.mwan:
                    # May have different number of wannier functions if nsppol == 2.
                    # Here I use the last value to fill eigens matrix (not very clean but oh well).
                    eigens[spin, ik, num_wan:self.mwan] = oeigs[-1]
                    if write_warning:
                        cprint("Different number of wannier functions for spin. Filling last bands with oeigs[-1]",
                               "yellow")
                        write_warning = False

        print("Interpolation completed in %.3f [s]" % (time.time() - start))
        occfacts = np.zeros_like(eigens)

        return ElectronBands(self.structure, kpoints, eigens, self.ebands.fermie,
                             occfacts, self.ebands.nelect, self.nspinor, self.nspden,
                             smearing=self.ebands.smearing)
Beispiel #7
0
    def test_irredzone_api(self):
        """Testing IrredZone API."""
        structure = abilab.Structure.as_structure(abidata.cif_file("si.cif"))

        ibz = IrredZone.from_ngkpt(structure,
                                   ngkpt=[4, 4, 4],
                                   shiftk=[0.0, 0.0, 0.0],
                                   verbose=2)
        repr(ibz)
        str(ibz)
        assert ibz.to_string(verbose=2)
        assert ibz.is_ibz
        assert len(ibz) == 8
        assert ibz.ksampling.kptopt == 1
        self.assert_equal(ibz.ksampling.mpdivs, [4, 4, 4])

        ibz = IrredZone.from_kppa(structure,
                                  kppa=1000,
                                  shiftk=[0.5, 0.5, 0.5],
                                  kptopt=1,
                                  verbose=1)
        assert ibz.is_ibz
        assert len(ibz) == 60
        self.assert_equal(ibz.ksampling.mpdivs, [8, 8, 8])
Beispiel #8
0
    def get_interpolated_ebands_plotter(self, vertices_names=None, knames=None, line_density=20,
            ngkpt=None, shiftk=(0, 0, 0), kpoints=None, **kwargs):
        """
        Args:
            vertices_names: Used to specify the k-path for the interpolated QP band structure
                It's a list of tuple, each tuple is of the form (kfrac_coords, kname) where
                kfrac_coords are the reduced coordinates of the k-point and kname is a string with the name of
                the k-point. Each point represents a vertex of the k-path. ``line_density`` defines
                the density of the sampling. If None, the k-path is automatically generated according
                to the point group of the system.
            knames: List of strings with the k-point labels defining the k-path. It has precedence over `vertices_names`.
            line_density: Number of points in the smallest segment of the k-path. Used with ``vertices_names``.
            ngkpt: Mesh divisions. Used if bands should be interpolated in the IBZ.
            shiftk: Shifts for k-meshs. Used with ngkpt.
            kpoints: |KpointList| object taken e.g from a previous ElectronBands.
                Has precedence over vertices_names and line_density.

        Return: |ElectronBandsPlotter| object.
        """
        diff_str = self.has_different_structures()
        if diff_str: cprint(diff_str, "yellow")

        # Need KpointList object (assume same structures in Robot)
        nc0 = self.abifiles[0]
        if kpoints is None:
            if ngkpt is not None:
                # IBZ sampling
                kpoints = IrredZone.from_ngkpt(nc0.structure, ngkpt, shiftk, kptopt=1, verbose=0)
            else:
                # K-Path
                if knames is not None:
                    kpoints = Kpath.from_names(nc0.structure, knames, line_density=line_density)
                else:
                    if vertices_names is None:
                        vertices_names = [(k.frac_coords, k.name) for k in nc0.structure.hsym_kpoints]
                    kpoints = Kpath.from_vertices_and_names(nc0.structure, vertices_names, line_density=line_density)

        plotter = ElectronBandsPlotter()
        for label, abiwan in self.items():
            plotter.add_ebands(label, abiwan.interpolate_ebands(kpoints=kpoints))

        return plotter
Beispiel #9
0
def main():

    def show_examples_and_exit(err_msg=None, error_code=1):
        """Display the usage of the script."""
        sys.stderr.write(get_epilog())
        if err_msg: sys.stderr.write("Fatal Error\n" + err_msg + "\n")
        sys.exit(error_code)

    parser = get_parser(with_epilog=True)

    # Parse command line.
    try:
        options = parser.parse_args()
    except Exception as exc:
        show_examples_and_exit(error_code=1)

    if not options.command:
        show_examples_and_exit(error_code=1)

    # loglevel is bound to the string value obtained from the command line argument.
    # Convert to upper case to allow the user to specify --loglevel=DEBUG or --loglevel=debug
    import logging
    numeric_level = getattr(logging, options.loglevel.upper(), None)
    if not isinstance(numeric_level, int):
        raise ValueError('Invalid log level: %s' % options.loglevel)
    logging.basicConfig(level=numeric_level)

    if options.verbose > 2:
        print(options)

    if options.command == "spglib":
        structure = abilab.Structure.from_file(options.filepath)
        print(structure.spget_summary(symprec=options.symprec, angle_tolerance=options.angle_tolerance,
                                      verbose=options.verbose))
        #remove_equivalent_atoms(structure)

    elif options.command == "abispg":
        structure = abilab.Structure.from_file(options.filepath)
        check_ordered_structure(structure)
        spgrp = structure.abi_spacegroup

        if spgrp is not None:
            print(structure.spget_summary(verbose=options.verbose))
        else:
            # Here we compare Abinit wrt spglib. If spgrp is None, we create a temporary
            # task to run the code in dry-run mode.
            print("FILE does not contain Abinit symmetry operations.")
            print("Calling Abinit in --dry-run mode with chkprim = 0 to get space group.")
            from abipy.data.hgh_pseudos import HGH_TABLE
            gsinp = factories.gs_input(structure, HGH_TABLE, spin_mode="unpolarized")
            gsinp["chkprim"] = 0
            abistructure = gsinp.abiget_spacegroup(tolsym=options.tolsym)
            print(abistructure.spget_summary(verbose=options.verbose))

            diff_structures([structure, abistructure], mode=options.diff_mode,
                            headers=["Input structure", "After Abinit symmetrization"], fmt="abivars")

            # Save file.
            save_structure(abistructure, options)

    elif options.command == "convert":
        fmt = options.format
        if fmt == "cif" and options.filepath.endswith(".cif"): fmt = "abivars"
        print(abilab.Structure.from_file(options.filepath).convert(fmt=fmt))

    elif options.command == "supercell":
        structure = abilab.Structure.from_file(options.filepath)

        options.scaling_matrix = np.array(options.scaling_matrix)
        if len(options.scaling_matrix) == 9:
            options.scaling_matrix.shape = (3, 3)
        if options.verbose:
            print("scaling matrix: ", options.scaling_matrix)

        supcell = structure * options.scaling_matrix
        #supcell = structure.make_supercell(scaling_matrix, to_unit_cell=True)
        print(supcell.convert(fmt=options.format))

    elif options.command == "abisanitize":
        print("\nCalling abi_sanitize to get a new structure in which:")
        print("    * Structure is refined.")
        print("    * Reduced to primitive settings.")
        print("    * Lattice vectors are exchanged if the triple product is negative\n")

        structure = abilab.Structure.from_file(options.filepath)
        sanitized = structure.abi_sanitize(symprec=options.symprec, angle_tolerance=options.angle_tolerance,
                                           primitive=not options.no_primitive, primitive_standard=options.primitive_standard)
        index = [options.filepath, "abisanitized"]
        dfs = abilab.dataframes_from_structures([structure, sanitized], index=index, with_spglib=True)

        abilab.print_dataframe(dfs.lattice, title="Lattice parameters:")
        abilab.print_dataframe(dfs.coords, title="Atomic positions (columns give the site index):")

        if not options.verbose:
            print("\nUse -v for more info")
            #print(sanitized.convert(fmt="cif"))
        else:
            #print("\nDifference between structures:")
            if len(structure) == len(sanitized):
                table = []
                for line1, line2 in zip(str(structure).splitlines(), str(sanitized).splitlines()):
                    table.append([line1, line2])
                print(str(tabulate(table, headers=["Initial structure", "Abisanitized"])))

            else:
                print("\nInitial structure:")
                print(structure)
                print("\nabisanitized structure:")
                print(sanitized)

        # Save file.
        save_structure(sanitized, options)

    elif options.command == "irefine":
        structure = abilab.Structure.from_file(options.filepath)
        sanitized = structure.copy()
        symprec, angle_tolerance = options.symprec, options.angle_tolerance
        print("Calling abi_sanitize with increasing tolerances to reach target space group:", options.target_spgnum)
        print("Using symprec_step: ", options.symprec_step, ", angle_tolerance_step:", options.angle_tolerance_step,
              "ntrial", options.ntrial)
        itrial = 0
        while itrial < options.ntrial:
            print(">>> Trying with symprec: %s, angle_tolerance: %s" % (symprec, angle_tolerance))
            sanitized = sanitized.abi_sanitize(symprec=symprec, angle_tolerance=angle_tolerance,
                primitive=not options.no_primitive, primitive_standard=options.primitive_standard)
            spg_symb, spg_num = sanitized.get_space_group_info(symprec=symprec, angle_tolerance=angle_tolerance)
            print(">>> Space-group number:", spg_symb, ", symbol:", spg_num, "for trial:", itrial)
            if spg_num == options.target_spgnum:
                print(2 * "\n", "# Final structure with space group number:", spg_symb, ", symbol:", spg_num, 2 *"\n")
                print(sanitized.convert(fmt="cif"))
                break

            # Increment counter and tols.
            itrial += 1
            symprec += options.symprec_step
            angle_tolerance += options.angle_tolerance_step
        else:
            print("Cannot find space group number:", options.target_spgnum, "after", options.ntrial, "iterations")
            return 1

        # Save file.
        #save_structure(sanitized, options)

    elif options.command == "conventional":
        print("\nCalling get_conventional_standard_structure to get conventional structure:")
        print("The standards are defined in Setyawan, W., & Curtarolo, S. (2010). ")
        print("High-throughput electronic band structure calculations: Challenges and tools. ")
        print("Computational Materials Science, 49(2), 299-312. doi:10.1016/j.commatsci.2010.05.010\n")

        structure = abilab.Structure.from_file(options.filepath)
        conv = structure.get_conventional_standard_structure(international_monoclinic=True,
                                           symprec=options.symprec, angle_tolerance=options.angle_tolerance)
        index = [options.filepath, "conventional"]
        dfs = abilab.dataframes_from_structures([structure, conv], index=index, with_spglib=True)

        abilab.print_dataframe(dfs.lattice, title="Lattice parameters:")
        if options.verbose:
            abilab.print_dataframe(dfs.coords, title="Atomic positions (columns give the site index):")

        if not options.verbose:
            print("\nUse -v for more info")
        else:
            #print("\nDifference between structures:")
            if len(structure) == len(conv):
                table = []
                for line1, line2 in zip(str(structure).splitlines(), str(conv).splitlines()):
                    table.append([line1, line2])
                print(str(tabulate(table, headers=["Initial structure", "Conventional"])))

            else:
                print("\nInitial structure:\n", structure)
                print("\nConventional structure:\n", conv)

        # Save file.
        save_structure(conv, options)

    elif options.command == "neighbors":
        abilab.Structure.from_file(options.filepath).print_neighbors(radius=options.radius)

    elif options.command == "interpolate":
        initial_structure = abilab.Structure.from_file(options.filepaths[0])
        end_structure = abilab.Structure.from_file(options.filepaths[1])
        structures = initial_structure.interpolate(end_structure, nimages=options.nimages,
                                                   interpolate_lattices=False, pbc=True,
                                                   autosort_tol=options.autosort_tol)
        structures = list(map(abilab.Structure.as_structure, structures))
        for i, s in enumerate(structures):
            print(marquee("Structure #%d" % i, mark="="))
            print(s.convert(fmt=options.format))
            print(" ")

    elif options.command == "xrd":
        structure = abilab.Structure.from_file(options.filepath)
        two_theta_range = tuple(float(t) for t in options.two_theta_range)
        structure.plot_xrd(wavelength=options.wavelength, two_theta_range=two_theta_range,
                           symprec=options.symprec, annotate_peaks=not options.no_annotate_peaks)

    elif options.command == "oxistate":
        print(abilab.Structure.from_file(options.filepath).get_oxi_state_decorated())

    elif options.command == "ipython":
        structure = abilab.Structure.from_file(options.filepath)
        print("Invoking Ipython, `structure` object will be available in the Ipython terminal")
        import IPython
        IPython.start_ipython(argv=[], user_ns={"structure": structure})

    elif options.command == "notebook":
        structure = abilab.Structure.from_file(options.filepath)
        structure.make_and_open_notebook(nbpath=None, foreground=options.foreground)

    elif options.command == "visualize":
        structure = abilab.Structure.from_file(options.filepath)
        print(structure)
        print("Visualizing structure with:", options.appname)
        structure.visualize(appname=options.appname)

    elif options.command == "kpath":
        structure = abilab.Structure.from_file(options.filepath)
        print(structure.get_kpath_input_string(fmt=options.format, line_density=10))

    elif options.command == "bz":
        abilab.Structure.from_file(options.filepath).plot_bz()

    elif options.command == "ngkpt":
        d = abilab.Structure.from_file(options.filepath).calc_ksampling(options.nksmall)
        print("ngkpt %d %d %d" % (d.ngkpt[0], d.ngkpt[1], d.ngkpt[2]))
        print("nshiftk ", len(d.shiftk), "\nshiftk")
        for s in d.shiftk:
            print("  %s %s %s" % (s[0], s[1], s[2]))

    elif options.command == "ktables":
        structure = abilab.Structure.from_file(options.filepath)
        k = Ktables(structure, options.mesh, options.is_shift, not options.no_time_reversal)
        print(k)
        print("")
        print("NB: These results are obtained by calling spglib with the structure read from file.")
        print("The k-points might differ from the ones expected by Abinit, especially if the space groups differ.")

        if not options.verbose:
            print("\nUse -v to obtain the BZ --> IBZ mapping.")
        else:
            print()
            k.print_bz2ibz()

    elif options.command == "abikmesh":
        structure = abilab.Structure.from_file(options.filepath)
        if options.kppa is None and options.ngkpt is None:
            raise ValueError("Either ngkpt or kppa must be provided")

        if options.kppa is not None:
            print("Calling Abinit to compute the IBZ with kppa:", options.kppa, "and shiftk:", options.shiftk)
            ibz = IrredZone.from_kppa(structure, options.kppa, options.shiftk,
                                      kptopt=options.kptopt, verbose=options.verbose)
        else:
            print("Calling Abinit to compute the IBZ with ngkpt:", options.ngkpt, "and shiftk:", options.shiftk)
            ibz = IrredZone.from_ngkpt(structure, options.ngkpt, options.shiftk,
                                       kptopt=options.kptopt, verbose=options.verbose)

        print(ibz.to_string(verbose=options.verbose))

    #elif options.command == "kmesh_jhu":
    #    structure = abilab.Structure.from_file(options.filepath)
    #    ksampling = structure.ksampling_from_jhudb(kppra=1000)
    #    #print(ksampling)

    elif options.command == "lgk":
        structure = abilab.Structure.from_file(options.filepath)
        spgrp = structure.abi_spacegroup
        if spgrp is None:
            cprint("Your file does not contain Abinit symmetry operations.", "yellow")
            cprint("Will call spglib to obtain the space group (assuming time-reversal: %s)" %
                   (not options.no_time_reversal), "yellow")
            spgrp = AbinitSpaceGroup.from_structure(structure, has_timerev=not options.no_time_reversal,
                        symprec=options.symprec, angle_tolerance=options.angle_tolerance)
        print()
        print(marquee("Structure", mark="="))
        print(structure.spget_summary(verbose=options.verbose))
        print("\n")

        print(marquee("Little Group", mark="="))
        ltk = spgrp.find_little_group(kpoint=options.kpoint)
        print(ltk.to_string(verbose=options.verbose))

    elif options.command == "kstar":
        structure = abilab.Structure.from_file(options.filepath)

        # Call spglib to get spacegroup if Abinit spacegroup is not available.
        if structure.abi_spacegroup is None:
            structure.spgset_abi_spacegroup(has_timerev=not options.no_time_reversal)

        kpoint = Kpoint(options.kpoint, structure.reciprocal_lattice)
        kstar = kpoint.compute_star(structure.abi_spacegroup, wrap_tows=True)
        print("Found %s points in the star of %s\n" % (len(kstar), repr(kpoint)))
        for k in kstar:
            print(4 * " ", repr(k))

    elif options.command == "keq":
        structure = abilab.Structure.from_file(options.filepath)

        # Call spglib to get spacegroup if Abinit spacegroup is not available.
        if structure.abi_spacegroup is None:
            structure.spgset_abi_spacegroup(has_timerev=not options.no_time_reversal)

        k1, k2 = options.kpoints[:3], options.kpoints[3:6]
        k1tab = structure.abi_spacegroup.symeq(k1, k2)

        if k1tab.isym != -1:
            print("\nk1:", k1, "and k2:", k2, "are symmetry equivalent k-points\n")
            print("Related by the symmetry operation (reduced coords):\n", k1tab.op)
            print("With umklapp vector Go = TO(k1) - k2 =", k1tab.g0)
        else:
            print(k1, "and", k2, "are NOT symmetry equivalent")

    elif options.command == "mp_id":
        # Get the Structure corresponding to material_id.
        structure = abilab.Structure.from_mpid(options.mpid, final=True,
                                               api_key=options.mapi_key, endpoint=options.endpoint)
        # Convert to format and print it.
        print(structure.convert(fmt=options.format))

    elif options.command == "mp_match":
        mp = abilab.mp_match_structure(options.filepath)
        if not mp.structures:
            cprint("No structure found in database", "yellow")
            return 1

        if options.notebook:
            return mp.make_and_open_notebook(foreground=options.foreground)
        else:
            mp.print_results(fmt=options.format, verbose=options.verbose)

        if options.browser:
            mp.open_browser(limit=None if options.verbose == 2 else 10)

    elif options.command == "mp_search":
        mp = abilab.mp_search(options.chemsys_formula_id)
        if not mp.structures:
            cprint("No structure found in Materials Project database", "yellow")
            return 1
        if options.select_spgnum: mp = mp.filter_by_spgnum(options.select_spgnum)

        if options.notebook:
            return mp.make_and_open_notebook(foreground=options.foreground)
        else:
            mp.print_results(fmt=options.format, verbose=options.verbose)

        if options.browser:
            mp.open_browser(limit=None if options.verbose == 2 else 10)

    elif options.command == "mp_pd":
        if os.path.exists(options.file_or_elements):
            structure = abilab.Structure.from_file(options.file_or_elements)
            elements = structure.symbol_set
        else:
            elements = options.file_or_elements.split("-")

        if options.verbose > 1: print("Building phase-diagram for elements:", elements)
        with abilab.restapi.get_mprester(api_key=options.mapi_key, endpoint=options.endpoint) as rest:
            pdr = rest.get_phasediagram_results(elements)
            pdr.print_dataframes(verbose=options.verbose)
            pdr.plot(show_unstable=options.show_unstable)

    elif options.command == "cod_search":
        cod = abilab.cod_search(options.formula, primitive=options.primitive)
        if not cod.structures:
            cprint("No structure found in COD database", "yellow")
            return 1
        if options.select_spgnum: cod = cod.filter_by_spgnum(options.select_spgnum)

        if options.notebook:
            return cod.make_and_open_notebook(foreground=options.foreground)
        else:
            cod.print_results(fmt=options.format, verbose=options.verbose)

    elif options.command == "cod_id":
        # Get the Structure from COD
        structure = abilab.Structure.from_cod_id(options.cod_identifier, primitive=options.primitive)
        # Convert to format and print it.
        print(structure.convert(fmt=options.format))

    elif options.command == "animate":
        filepath = options.filepath
        if any(filepath.endswith(ext) for ext in ("HIST", "HIST.nc")):
            with abilab.abiopen(filepath) as hist:
                structures = hist.structures

        elif "XDATCAR" in filepath:
            structures = Xdatcar(filepath).structures
            if not structures:
                raise RuntimeError("Your Xdatcar contains only one structure. Due to a bug "
                    "in the pymatgen routine, your structures won't be parsed correctly"
                    "Solution: Add another structure at the end of the file.")
        else:
            raise ValueError("Don't know how to handle file %s" % filepath)

        xsf_write_structure(sys.stdout, structures)

    else:
        raise ValueError("Unsupported command: %s" % options.command)

    return 0