def test_utils(self): """Test utilities for the generation of Abinit inputs.""" # Test as_structure and from/to abivars si = Structure.as_structure(abidata.cif_file("si.cif")) assert si.formula == "Si2" assert si.latex_formula == "Si$_{2}$" assert si.abi_spacegroup is None and not si.has_abi_spacegroup assert "ntypat" in si.to(fmt="abivars") spgroup = si.spgset_abi_spacegroup(has_timerev=True) assert spgroup is not None assert si.has_abi_spacegroup assert si.abi_spacegroup.spgid == 227 kfrac_coords = si.get_kcoords_from_names(["G", "X", "L", "Gamma"]) self.assert_equal(kfrac_coords, ([[0. , 0. , 0. ], [0.5, 0. , 0.5], [0.5, 0.5, 0.5], [0. , 0. , 0. ]])) si_wfk = Structure.as_structure(abidata.ref_file("si_scf_WFK.nc")) assert si_wfk.formula == "Si2" si_wfk.print_neighbors(radius=2.5) assert si_wfk.has_abi_spacegroup # Cannot change spacegroup with self.assertRaises(ValueError): si_wfk.spgset_abi_spacegroup(has_timerev=True) # K and U are equivalent. [5/8, 1/4, 5/8] should return U assert si_wfk.findname_in_hsym_stars([3/8, 3/8, 3/4]) == "K" assert si_wfk.findname_in_hsym_stars([5/8, 1/4, 5/8]) == "U" # TODO: Fix order of atoms in supercells. # Test __mul__, __rmul__ (should return Abipy structures) assert si_wfk == 1 * si_wfk supcell = si_wfk * [2, 2, 2] assert len(supcell) == 8 * len(si_wfk) and hasattr(supcell, "abi_string") si_abi = Structure.from_file(abidata.ref_file("refs/si_ebands/run.abi")) assert si_abi.formula == "Si2" self.assert_equal(si_abi.frac_coords, [[0, 0, 0], [0.25, 0.25, 0.25]]) si_abo = Structure.from_file(abidata.ref_file("refs/si_ebands/run.abo")) assert si_abo == si_abi assert "ntypat" in si_abi.to(fmt="abivars") znse = Structure.from_file(abidata.ref_file("refs/znse_phonons/ZnSe_hex_qpt_DDB")) assert len(znse) == 4 assert znse.formula == "Zn2 Se2" self.assert_almost_equal(znse.frac_coords.flat, [ 0.33333333333333, 0.66666666666667, 0.99962203020000, 0.66666666666667, 0.33333333333333, 0.49962203020000, 0.33333333333333, 0.66666666666667, 0.62537796980000, 0.66666666666667, 0.33333333333333, 0.12537796980000]) from abipy.core.structure import diff_structures diff_structures([si_abi, znse], headers=["si_abi", "znse"], fmt="abivars", mode="table") diff_structures([si_abi, znse], headers=["si_abi", "znse"], fmt="abivars", mode="diff") # From pickle file. import pickle tmp_path = self.get_tmpname(suffix=".pickle") with open(tmp_path, "wb") as fh: pickle.dump(znse, fh) same_znse = Structure.from_file(tmp_path) assert same_znse == znse same_znse = Structure.as_structure(tmp_path) assert same_znse == znse for fmt in ["abivars", "cif", "POSCAR", "json", "xsf", "qe", "siesta", "wannier90"]: assert len(znse.convert(fmt=fmt)) > 0 for fmt in ["abinit", "w90", "siesta"]: assert len(znse.get_kpath_input_string(fmt=fmt)) > 0 oxi_znse = znse.get_oxi_state_decorated() assert len(oxi_znse.abi_string) from pymatgen.core.periodic_table import Specie assert Specie("Zn", 2) in oxi_znse.composition.elements assert Specie("Se", -2) in oxi_znse.composition.elements system = si.spget_lattice_type() assert system == "cubic" e = si.spget_equivalent_atoms(printout=True) assert len(e.irred_pos) == 1 self.assert_equal(e.eqmap[0], [0, 1]) for irr_pos in e.irred_pos: assert len(e.eqmap[irr_pos]) > 0 assert "equivalent_atoms" in e.spgdata if self.has_matplotlib(): assert si.plot_bz(show=False) assert si.plot_bz(pmg_path=False, show=False) assert si.plot(show=False) if sys.version[0:3] > '2.7': # pmg broke py compatibility assert si.plot_xrd(show=False) if self.has_mayavi(): #assert si.plot_vtk(show=False) # Disabled due to (core dumped) on travis assert si.plot_mayaview(show=False) if self.has_panel(): assert hasattr(si.get_panel(), "show") assert si is Structure.as_structure(si) assert si == Structure.as_structure(si.to_abivars()) assert si == Structure.from_abivars(si.to_abivars()) assert len(si.abi_string) assert si.reciprocal_lattice == si.lattice.reciprocal_lattice kptbounds = si.calc_kptbounds() ksamp = si.calc_ksampling(nksmall=10) shiftk = [[ 0.5, 0.5, 0.5], [ 0.5, 0. , 0. ], [ 0. , 0.5, 0. ], [ 0. , 0. , 0.5]] self.assert_equal(si.calc_ngkpt(nksmall=2), [2, 2, 2]) self.assert_equal(si.calc_shiftk(), shiftk) self.assert_equal(ksamp.ngkpt, [10, 10, 10]) self.assert_equal(ksamp.shiftk, shiftk) lif = Structure.from_abistring(""" acell 7.7030079150 7.7030079150 7.7030079150 Angstrom rprim 0.0000000000 0.5000000000 0.5000000000 0.5000000000 0.0000000000 0.5000000000 0.5000000000 0.5000000000 0.0000000000 natom 2 ntypat 2 typat 1 2 znucl 3 9 xred 0.0000000000 0.0000000000 0.0000000000 0.5000000000 0.5000000000 0.5000000000 """) assert lif.formula == "Li1 F1" same = Structure.rocksalt(7.7030079150, ["Li", "F"], units="ang") self.assert_almost_equal(lif.lattice.a, same.lattice.a) si = Structure.from_mpid("mp-149") assert si.formula == "Si2" # Test abiget_spginfo d = si.abiget_spginfo(tolsym=None, pre="abi_") assert d["abi_spg_symbol"] == "Fd-3m" assert d["abi_spg_number"] == 227 assert d["abi_bravais"] == "Bravais cF (face-center cubic)" llzo = Structure.from_file(abidata.cif_file("LLZO_oxi.cif")) assert llzo.is_ordered d = llzo.abiget_spginfo(tolsym=0.001) assert d["spg_number"] == 142 mgb2_cod = Structure.from_cod_id(1526507, primitive=True) assert mgb2_cod.formula == "Mg1 B2" assert mgb2_cod.spget_lattice_type() == "hexagonal" mgb2 = abidata.structure_from_ucell("MgB2") if self.has_ase(): mgb2.abi_primitive() assert [site.species_string for site in mgb2.get_sorted_structure_z()] == ["B", "B", "Mg"] s2inds = mgb2.get_symbol2indices() self.assert_equal(s2inds["Mg"], [0]) self.assert_equal(s2inds["B"], [1, 2]) s2coords = mgb2.get_symbol2coords() self.assert_equal(s2coords["Mg"], [[0, 0, 0]]) self.assert_equal(s2coords["B"], [[1/3, 2/3, 0.5], [2/3, 1/3, 0.5]]) new_mgb2 = mgb2.scale_lattice(mgb2.volume * 1.1) self.assert_almost_equal(new_mgb2.volume, mgb2.volume * 1.1) assert new_mgb2.lattice.is_hexagonal # TODO: This part should be tested more carefully mgb2.abi_sanitize() mgb2.abi_sanitize(primitive_standard=True) mgb2.get_conventional_standard_structure() assert len(mgb2.abi_string) assert len(mgb2.spget_summary(site_symmetry=True, verbose=10)) self.serialize_with_pickle(mgb2) pseudos = abidata.pseudos("12mg.pspnc", "5b.pspnc") nv = mgb2.num_valence_electrons(pseudos) assert nv == 8 and isinstance(nv , int) assert mgb2.valence_electrons_per_atom(pseudos) == [2, 3, 3] self.assert_equal(mgb2.calc_shiftk() , [[0.0, 0.0, 0.5]]) bmol = Structure.boxed_molecule(pseudos, cart_coords=[[0, 0, 0], [5, 5, 5]], acell=[10, 10, 10]) self.assert_almost_equal(bmol.volume, (10 * bohr_to_ang) ** 3) # FIXME This is buggy #acell = np.array([10, 20, 30]) #batom = Structure.boxed_atom(abidata.pseudo("12mg.pspnc"), cart_coords=[1, 2, 3], acell=acell) #assert isinstance(batom, Structure) #assert len(batom.cart_coords) == 1 #self.assert_equal(batom.cart_coords[0], [1, 2, 3]) # Function to compute cubic a0 from primitive v0 (depends on struct_type) vol2a = {"fcc": lambda vol: (4 * vol) ** (1/3.), "bcc": lambda vol: (2 * vol) ** (1/3.), "zincblende": lambda vol: (4 * vol) ** (1/3.), "rocksalt": lambda vol: (4 * vol) ** (1/3.), "ABO3": lambda vol: vol ** (1/3.), "hH": lambda vol: (4 * vol) ** (1/3.), } a = 10 bcc_prim = Structure.bcc(a, ["Si"], primitive=True) assert len(bcc_prim) == 1 self.assert_almost_equal(a, vol2a["bcc"](bcc_prim.volume)) bcc_conv = Structure.bcc(a, ["Si"], primitive=False) assert len(bcc_conv) == 2 self.assert_almost_equal(a**3, bcc_conv.volume) fcc_prim = Structure.fcc(a, ["Si"], primitive=True) assert len(fcc_prim) == 1 self.assert_almost_equal(a, vol2a["fcc"](fcc_prim.volume)) fcc_conv = Structure.fcc(a, ["Si"], primitive=False) assert len(fcc_conv) == 4 self.assert_almost_equal(a**3, fcc_conv.volume) zns = Structure.zincblende(a / bohr_to_ang, ["Zn", "S"], units="bohr") self.assert_almost_equal(a, vol2a["zincblende"](zns.volume)) rock = Structure.rocksalt(a, ["Na", "Cl"]) assert len(rock) == 2 self.assert_almost_equal(a, vol2a["rocksalt"](rock.volume)) perov = Structure.ABO3(a, ["Ca", "Ti", "O", "O", "O"]) assert len(perov) == 5 self.assert_almost_equal(a**3, perov.volume) # Test notebook generation. if self.has_nbformat(): assert mgb2.write_notebook(nbpath=self.get_tmpname(text=True))
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) 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("# Abinit Structure") print(structure.abi_string) print("\n# K-path in reduced coordinates:") print("# tolwfr 1e-20 iscf -2 getden ??") print(" ndivsm 10") print(" kptopt", -(len(structure.hsym_kpoints) - 1)) print(" kptbounds") for k in structure.hsym_kpoints: print(" %+.5f %+.5f %+.5f" % tuple(k.frac_coords), "#", k.name) 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) from abipy.data.hgh_pseudos import HGH_TABLE gsinp = factories.gs_input(structure, HGH_TABLE, spin_mode="unpolarized", kppa=options.kppa) if options.kppa is not None: print("Calling Abinit to compute the IBZ with kppa:", options.kppa, "and shiftk:", options.shiftk) options.ngkpt = None else: print("Calling Abinit to compute the IBZ with ngkpt:", options.ngkpt, "and shiftk", options.shiftk) ibz = gsinp.abiget_ibz(ngkpt=options.ngkpt, shiftk=options.shiftk, kptopt=options.kptopt) if options.verbose: print(gsinp) print("Found %d points in the IBZ:" % len(ibz.points)) for i, (k, w) in enumerate(zip(ibz.points, ibz.weights)): print("%6d) [%+.3f, %+.3f, %+.3f] weight=%.3f" % (i, k[0], k[1], k[2], w)) #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) # TODO #kstar = structure.get_star_kpoint(options.kpoint, has_timerev=not options.no_time_reversal) # 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 == "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
def test_utils(self): """Test utilities for the generation of Abinit inputs.""" # Test as_structure and from/to abivars si = Structure.as_structure(abidata.cif_file("si.cif")) assert si.formula == "Si2" assert si.latex_formula == "Si$_{2}$" assert si.abi_spacegroup is None and not si.has_abi_spacegroup assert "ntypat" in si.to(fmt="abivars") spgroup = si.spgset_abi_spacegroup(has_timerev=True) assert spgroup is not None assert si.has_abi_spacegroup assert si.abi_spacegroup.spgid == 227 kfrac_coords = si.get_kcoords_from_names(["G", "X", "L", "Gamma"]) self.assert_equal(kfrac_coords, ([[0. , 0. , 0. ], [0.5, 0. , 0.5], [0.5, 0.5, 0.5], [0. , 0. , 0. ]])) with self.assertRaises(TypeError): Structure.as_structure({}) with self.assertRaises(TypeError): Structure.as_structure([]) si_wfk = Structure.as_structure(abidata.ref_file("si_scf_WFK.nc")) assert si_wfk.formula == "Si2" si_wfk.print_neighbors(radius=2.5) assert si_wfk.has_abi_spacegroup # Cannot change spacegroup with self.assertRaises(ValueError): si_wfk.spgset_abi_spacegroup(has_timerev=True) # K and U are equivalent. [5/8, 1/4, 5/8] should return U assert si_wfk.findname_in_hsym_stars([3/8, 3/8, 3/4]) == "K" assert si_wfk.findname_in_hsym_stars([5/8, 1/4, 5/8]) == "U" # TODO: Fix order of atoms in supercells. # Test __mul__, __rmul__ (should return Abipy structures) assert si_wfk == 1 * si_wfk supcell = si_wfk * [2, 2, 2] assert len(supcell) == 8 * len(si_wfk) and hasattr(supcell, "abi_string") si_abi = Structure.from_file(abidata.ref_file("refs/si_ebands/run.abi")) assert si_abi.formula == "Si2" self.assert_equal(si_abi.frac_coords, [[0, 0, 0], [0.25, 0.25, 0.25]]) si_abo = Structure.from_file(abidata.ref_file("refs/si_ebands/run.abo")) assert si_abo == si_abi assert "ntypat" in si_abi.to(fmt="abivars") znse = Structure.from_file(abidata.ref_file("refs/znse_phonons/ZnSe_hex_qpt_DDB")) assert len(znse) == 4 assert znse.formula == "Zn2 Se2" self.assert_almost_equal(znse.frac_coords.flat, [ 0.33333333333333, 0.66666666666667, 0.99962203020000, 0.66666666666667, 0.33333333333333, 0.49962203020000, 0.33333333333333, 0.66666666666667, 0.62537796980000, 0.66666666666667, 0.33333333333333, 0.12537796980000]) from abipy.core.structure import diff_structures diff_structures([si_abi, znse], headers=["si_abi", "znse"], fmt="abivars", mode="table") diff_structures([si_abi, znse], headers=["si_abi", "znse"], fmt="abivars", mode="diff") # From pickle file. import pickle tmp_path = self.get_tmpname(suffix=".pickle") with open(tmp_path, "wb") as fh: pickle.dump(znse, fh) same_znse = Structure.from_file(tmp_path) assert same_znse == znse same_znse = Structure.as_structure(tmp_path) assert same_znse == znse for fmt in ["abivars", "cif", "POSCAR", "json", "xsf", "qe", "siesta", "wannier90"]: assert len(znse.convert(fmt=fmt)) > 0 for fmt in ["abinit", "w90", "siesta"]: assert len(znse.get_kpath_input_string(fmt=fmt)) > 0 oxi_znse = znse.get_oxi_state_decorated() assert len(oxi_znse.abi_string) from pymatgen.core.periodic_table import Specie assert Specie("Zn", 2) in oxi_znse.composition.elements assert Specie("Se", -2) in oxi_znse.composition.elements system = si.spget_lattice_type() assert system == "cubic" e = si.spget_equivalent_atoms(printout=True) assert len(e.irred_pos) == 1 self.assert_equal(e.eqmap[0], [0, 1]) for irr_pos in e.irred_pos: assert len(e.eqmap[irr_pos]) > 0 assert "equivalent_atoms" in e.spgdata if self.has_matplotlib(): assert si.plot_bz(show=False) assert si.plot_bz(pmg_path=False, show=False) assert si.plot(show=False) if sys.version[0:3] > '2.7': # pmg broke py compatibility assert si.plot_xrd(show=False) if self.has_mayavi(): #assert si.vtkview(show=False) # Disabled due to (core dumped) on travis assert si.mayaview(show=False) assert si is Structure.as_structure(si) assert si == Structure.as_structure(si.to_abivars()) assert si == Structure.from_abivars(si.to_abivars()) assert len(si.abi_string) assert si.reciprocal_lattice == si.lattice.reciprocal_lattice kptbounds = si.calc_kptbounds() ksamp = si.calc_ksampling(nksmall=10) shiftk = [[ 0.5, 0.5, 0.5], [ 0.5, 0. , 0. ], [ 0. , 0.5, 0. ], [ 0. , 0. , 0.5]] self.assert_equal(si.calc_ngkpt(nksmall=2), [2, 2, 2]) self.assert_equal(si.calc_shiftk(), shiftk) self.assert_equal(ksamp.ngkpt, [10, 10, 10]) self.assert_equal(ksamp.shiftk, shiftk) si = Structure.from_mpid("mp-149") assert si.formula == "Si2" # Test abiget_spginfo d = si.abiget_spginfo(tolsym=None, pre="abi_") assert d["abi_spg_symbol"] == "Fd-3m" assert d["abi_spg_number"] == 227 assert d["abi_bravais"] == "Bravais cF (face-center cubic)" llzo = Structure.from_file(abidata.cif_file("LLZO_oxi.cif")) assert llzo.is_ordered d = llzo.abiget_spginfo(tolsym=0.001) assert d["spg_number"] == 142 mgb2_cod = Structure.from_cod_id(1526507, primitive=True) assert mgb2_cod.formula == "Mg1 B2" assert mgb2_cod.spget_lattice_type() == "hexagonal" mgb2 = abidata.structure_from_ucell("MgB2") if self.has_ase(): mgb2.abi_primitive() assert [site.species_string for site in mgb2.get_sorted_structure_z()] == ["B", "B", "Mg"] s2inds = mgb2.get_symbol2indices() self.assert_equal(s2inds["Mg"], [0]) self.assert_equal(s2inds["B"], [1, 2]) s2coords = mgb2.get_symbol2coords() self.assert_equal(s2coords["Mg"], [[0, 0, 0]]) self.assert_equal(s2coords["B"], [[1/3, 2/3, 0.5], [2/3, 1/3, 0.5]]) # TODO: This part should be tested more carefully mgb2.abi_sanitize() mgb2.abi_sanitize(primitive_standard=True) mgb2.get_conventional_standard_structure() assert len(mgb2.abi_string) assert len(mgb2.spget_summary(verbose=10)) #print(structure._repr_html_()) self.serialize_with_pickle(mgb2) pseudos = abidata.pseudos("12mg.pspnc", "5b.pspnc") nv = mgb2.num_valence_electrons(pseudos) assert nv == 8 and isinstance(nv , int) assert mgb2.valence_electrons_per_atom(pseudos) == [2, 3, 3] self.assert_equal(mgb2.calc_shiftk() , [[0.0, 0.0, 0.5]]) bmol = Structure.boxed_molecule(pseudos, cart_coords=[[0, 0, 0], [5, 5, 5]], acell=[10, 10, 10]) self.assert_almost_equal(bmol.volume, (10 * bohr_to_ang) ** 3) # FIXME This is buggy #acell = np.array([10, 20, 30]) #batom = Structure.boxed_atom(abidata.pseudo("12mg.pspnc"), cart_coords=[1, 2, 3], acell=acell) #assert isinstance(batom, Structure) #assert len(batom.cart_coords) == 1 #self.assert_equal(batom.cart_coords[0], [1, 2, 3]) # Function to compute cubic a0 from primitive v0 (depends on struct_type) vol2a = {"fcc": lambda vol: (4 * vol) ** (1/3.), "bcc": lambda vol: (2 * vol) ** (1/3.), "zincblende": lambda vol: (4 * vol) ** (1/3.), "rocksalt": lambda vol: (4 * vol) ** (1/3.), "ABO3": lambda vol: vol ** (1/3.), "hH": lambda vol: (4 * vol) ** (1/3.), } a = 10 bcc_prim = Structure.bcc(a, ["Si"], primitive=True) assert len(bcc_prim) == 1 self.assert_almost_equal(a, vol2a["bcc"](bcc_prim.volume)) bcc_conv = Structure.bcc(a, ["Si"], primitive=False) assert len(bcc_conv) == 2 self.assert_almost_equal(a**3, bcc_conv.volume) fcc_prim = Structure.fcc(a, ["Si"], primitive=True) assert len(fcc_prim) == 1 self.assert_almost_equal(a, vol2a["fcc"](fcc_prim.volume)) fcc_conv = Structure.fcc(a, ["Si"], primitive=False) assert len(fcc_conv) == 4 self.assert_almost_equal(a**3, fcc_conv.volume) zns = Structure.zincblende(a / bohr_to_ang, ["Zn", "S"], units="bohr") self.assert_almost_equal(a, vol2a["zincblende"](zns.volume)) rock = Structure.rocksalt(a, ["Na", "Cl"]) assert len(rock) == 2 self.assert_almost_equal(a, vol2a["rocksalt"](rock.volume)) perov = Structure.ABO3(a, ["Ca", "Ti", "O", "O", "O"]) assert len(perov) == 5 self.assert_almost_equal(a**3, perov.volume) # Test notebook generation. if self.has_nbformat(): assert mgb2.write_notebook(nbpath=self.get_tmpname(text=True))
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