def build_structure(self, ref="ae"): """ Returns the crystalline structure associated to this entry. Use the optimized lattice parameters obtained from reference ref. Returns None if no lattice parameter is available. """ # Get structure type and lattice parameters stype, a = self.struct_type, getattr(self, ref) # Handle missing value. if a is None: return None if stype == "bcc": return Structure.bcc(a, species=[self.symbol]) elif stype == "fcc": return Structure.fcc(a, species=[self.symbol]) elif stype == "rocksalt": return Structure.rocksalt(a, self.species) elif stype == "ABO3": return Structure.ABO3(a, self.species) elif stype == "hH": raise NotImplementedError() #return Structure.hH(a, sites) raise ValueError("Don't know how to construct %s structure" % stype)
def build_structure(self, ref="ae"): """ Returns the crystalline structure associated to this entry. Use the optimized lattice parameters obtained from reference ref. Returns None if no lattice parameter is available. """ # Get structure type and lattice parameters stype, a = self.struct_type, getattr(self, ref) # Handle missing value. if a is None: return None if stype == "bcc": return Structure.bcc(a, species=[self.symbol]) elif stype == "fcc": return Structure.fcc(a, species=[self.symbol]) elif stype == "rocksalt": return Structure.rocksalt(a, self.species) elif stype == "ABO3": return Structure.ABO3(a, self.species) elif stype == "hH": return half_heusler(a, self.species) raise ValueError("Don't know how to construct %s structure" % stype)
def __init__(self, a_guess, struct_type, pseudo, ecut_list=None, pawecutdg=None, ngkpt=(8, 8, 8), spin_mode="unpolarized", include_soc=False, tolvrs=1.e-10, smearing="fermi_dirac:0.001 Ha", ecutsm=0.05, chksymbreak=0, workdir=None, manager=None): """ Build a :class:`Work` for the computation of the relaxed lattice parameter. Args: structure_type: fcc, bcc pseudo: :class:`Pseudo` object. ecut_list: Cutoff energy in Hartree ngkpt: MP divisions. spin_mode: Spin polarization mode. toldfe: Tolerance on the energy (Ha) smearing: Smearing technique. workdir: String specifing the working directory. manager: :class:`TaskManager` responsible for the submission of the tasks. """ super(RelaxWithGbrvParamsWork, self).__init__(workdir=workdir, manager=manager) self_pseudo = pseudo self.include_soc = include_soc self.struct_type = struct_type if struct_type == "bcc": structure = Structure.bcc(a_guess, species=[pseudo.symbol]) elif struct_type == "fcc": structure = Structure.fcc(a_guess, species=[pseudo.symbol]) # Set extra_abivars. extra_abivars = dict( pawecutdg=pawecutdg, tolvrs=tolvrs, prtwf=-1, fband=3.0, nstep=100, ntime=50, ecutsm=ecutsm, dilatmx=1.1, ) self.ecut_list = ecut_list smearing = Smearing.as_smearing(smearing) # Kpoint sampling: shiftk depends on struct_type shiftk = {"fcc": [0, 0, 0], "bcc": [0.5, 0.5, 0.5]}.get(struct_type) spin_mode = SpinMode.as_spinmode(spin_mode) ksampling = KSampling.monkhorst(ngkpt, chksymbreak=chksymbreak, shiftk=shiftk, use_time_reversal=spin_mode.nspinor==1) relax_algo = RelaxationMethod.atoms_and_cell() inp = abilab.AbinitInput(structure, pseudo) inp.add_abiobjects(ksampling, relax_algo, spin_mode, smearing) inp.set_vars(extra_abivars) # Register structure relaxation task. for ecut in self.ecut_list: self.relax_task = self.register_relax_task(inp.new_with_vars(ecut=ecut))
def read_all_structures(self): """Return the list of structures at the different iteration steps.""" rprimd_list = self.read_value("rprimd") xred_list = self.read_value("xred") # Alchemical mixing is not supported. num_pseudos = self.read_dimvalue("npsp") ntypat = self.read_dimvalue("ntypat") if num_pseudos != ntypat: raise NotImplementedError( "Alchemical mixing is not supported, num_pseudos != ntypat") znucl, typat = self.read_value("znucl"), self.read_value( "typat").astype(int) #print(znucl.dtype, typat) cart_forces_step = self.read_cart_forces(unit="eV ang^-1") structures = [] #print("typat", type(typat)) for step in range(self.num_steps): s = Structure.from_abivars( xred=xred_list[step], rprim=rprimd_list[step], acell=3 * [1.0], # FIXME ntypat, typat, znucl are missing! znucl=znucl, typat=typat, ) s.add_site_property("cartesian_forces", cart_forces_step[step]) structures.append(s) return structures
def __init__(self, nspinor, nsppol, nspden, datar, structure, iorder="c"): """ Args: nspinor: Number of spinorial components. nsppol: Number of spins. nspden: Number of spin density components. datar: [nspden, nx, ny, nz] array with the scalar field in real space. See also ``read_denpot``. structure: |Structure| object describing the crystalline structure. iorder: Order of the array. "c" for C ordering, "f" for Fortran ordering. """ self.nspinor, self.nsppol, self.nspden = nspinor, nsppol, nspden # Convert to Abipy Structure. self._structure = Structure.as_structure(structure) iorder = iorder.lower() assert iorder in ["f", "c"] if iorder == "f": # (z,x,y) --> (x,y,z) datar = transpose_last3dims(datar) # Init Mesh3D mesh_shape = datar.shape[-3:] self._mesh = Mesh3D(mesh_shape, structure.lattice.matrix) # Make sure we have the correct shape. self._datar = np.reshape(datar, (nspden,) + self.mesh.shape)
def read_all_structures(self): """Return the list of structures at the different iteration steps.""" rprimd_list = self.read_value("rprimd") xred_list = self.read_value("xred") # Alchemical mixing is not supported. num_pseudos = self.read_dimvalue("npsp") ntypat = self.read_dimvalue("ntypat") if num_pseudos != ntypat: raise NotImplementedError("Alchemical mixing is not supported, num_pseudos != ntypat") znucl, typat = self.read_value("znucl"), self.read_value("typat").astype(int) #print(znucl.dtype, typat) cart_forces_step = self.read_cart_forces(unit="eV ang^-1") structures = [] #print("typat", type(typat)) for step in range(self.num_steps): s = Structure.from_abivars( xred=xred_list[step], rprim=rprimd_list[step], acell=3 * [1.0], # FIXME ntypat, typat, znucl are missing! znucl=znucl, typat=typat, ) s.add_site_property("cartesian_forces", cart_forces_step[step]) structures.append(s) return structures
def from_gsinp(cls, workdir, gsinp, volumes, ngqpt, manager=None): """ Args: workdir: gsinp: volumes: ngqpt: manager: """ ngqpt = np.reshape(ngqpt, 3) flow = cls(workdir=workdir, manager=manager) # Construct len(volumes) works. Each work performs the structure relaxation # at fixed volume followed by DFPT calculation with the relaxed structure. for vol in volumes: # Build GS input file for new structure with rescaled volume. new_lattice = gsinp.structure.lattice.scale(vol) new_structure = Structure(new_lattice, gsinp.structure.species, gsinp.structure.frac_coords) new_input = gsinp.new_with_structure(new_structure) # Register work. work = RelaxAndPhononWork.from_gsinp(new_input, ngqpt, optcell=3, ionmov=3) flow.register_work(work) return flow
def ion_ioncell_relax_and_ebands_input(structure, pseudos, kppa=None, nband=None, ecut=None, pawecutdg=None, accuracy="normal", spin_mode="polarized", smearing="fermi_dirac:0.1 eV", charge=0.0, scf_algorithm=None): """ Returns a :class:`AbinitInput` for a structural relaxation. The first dataset optmizes the atomic positions at fixed unit cell. The second datasets optimizes both ions and unit cell parameters. Args: structure: :class:`Structure` object. pseudos: List of filenames or list of :class:`Pseudo` objects or :class:`PseudoTable` object. kppa: Defines the sampling used for the Brillouin zone. nband: Number of bands included in the SCF run. accuracy: Accuracy of the calculation. spin_mode: Spin polarization. smearing: Smearing technique. charge: Electronic charge added to the unit cell. scf_algorithm: Algorithm used for solving of the SCF cycle. """ structure = Structure.as_structure(structure) relax_multi = ion_ioncell_relax_input(structure, pseudos, kppa=kppa, nband=nband, ecut=ecut, pawecutdg=pawecutdg, accuracy=accuracy, spin_mode=spin_mode, smearing=smearing, charge=charge, scf_algorithm=scf_algorithm) ebands_multi = ebands_input(structure, pseudos, kppa=kppa, nscf_nband=None, ndivsm=15, ecut=ecut, pawecutdg=pawecutdg, scf_nband=None, accuracy=accuracy, spin_mode=spin_mode, smearing=smearing, charge=charge, scf_algorithm=scf_algorithm, dos_kppa=None) return relax_multi + ebands_multi
def scf_input(structure, pseudos, kppa=None, ecut=None, pawecutdg=None, nband=None, accuracy="normal", spin_mode="polarized", smearing="fermi_dirac:0.1 eV", charge=0.0, scf_algorithm=None, shift_mode="Monkhorst-Pack"): structure = Structure.as_structure(structure) abinit_input = AbinitInput(structure, pseudos) # Set the cutoff energies. abinit_input.set_vars(_find_ecut_pawecutdg(ecut, pawecutdg, abinit_input.pseudos)) # SCF calculation. kppa = _DEFAULTS.get("kppa") if kppa is None else kppa shifts = (0.5, 0.5, 0.5) if shift_mode[0].lower() == "m" else (0.0, 0.0, 0.0) scf_ksampling = aobj.KSampling.automatic_density(structure, kppa, chksymbreak=0, shifts=shifts) scf_electrons = aobj.Electrons(spin_mode=spin_mode, smearing=smearing, algorithm=scf_algorithm, charge=charge, nband=nband, fband=None) if spin_mode=="polarized": abinit_input.set_autospinat() if scf_electrons.nband is None: scf_electrons.nband = _find_scf_nband(structure, abinit_input.pseudos, scf_electrons,abinit_input.get('spinat', None)) abinit_input.set_vars(scf_ksampling.to_abivars()) abinit_input.set_vars(scf_electrons.to_abivars()) abinit_input.set_vars(_stopping_criterion("scf", accuracy)) return abinit_input
def set_structure(self, structure): structure = Structure.as_structure(structure) self._structure = structure if structure is None: return self.set_vars(**structure.to_abivars())
def read_structure(self): """ Overrides the ``read_structure`` method so that we always return an instance of AbiPy |Structure| object """ from abipy.core.structure import Structure return Structure.from_file(self.path)
def test_alpha_sio2(self): """Testing wyckoff positions for alpha-SiO2""" asi02 = Structure.from_file( os.path.join(abidata.dirpath, "refs", "mp-7000_DDB.bz2")) ss = asi02.site_symmetries df = ss.get_wyckoff_dataframe(verbose=2) df = df[df["element"] == "Si"] self.assert_equal(df["xfrac"].values, ["xfrac", "yfrac", "0.0"]) self.assert_equal(df["yfrac"].values, ["0.0", "yfrac", "yfrac"]) self.assert_equal(np.array(df["zfrac"].values, dtype=float), [0.833335, 0.5, 0.166665]) """ wyckoff site_symmetry Txx Tyy Tzz Txy Txz Tyz 0 3a 2 (#3,nsym:2) Txx Tyy Tzz Tyy/2 Tyz/2 Tyz 1 3a 2 (#3,nsym:2) Tyy Tyy Tzz Txy -Tyz Tyz 2 3a 2 (#3,nsym:2) 2*Txy Tyy Tzz Txy 2*Tyz Tyz """ df = ss.get_tensor_rank2_dataframe(verbose=2) ref = ["Txx", "Tyy", "2*Txy"] self.assert_equal(df["Txx"].values, ref) ref = ["Tyy", "Tyy", "Tyy"] self.assert_equal(df["Tyy"].values, ref) ref = ["Tzz", "Tzz", "Tzz"] self.assert_equal(df["Tzz"].values, ref) ref = ["Tyy/2", "Txy", "Txy"] self.assert_equal(df["Txy"].values, ref) ref = ["Tyz/2", "-Tyz", "2*Tyz"] self.assert_equal(df["Txz"].values, ref) ref = ["Tyz", "Tyz", "Tyz"] self.assert_equal(df["Tyz"].values, ref)
def ion_ioncell_relax_input(structure, pseudos, kppa=None, nband=None, ecut=None, pawecutdg=None, accuracy="normal", spin_mode="polarized", smearing="fermi_dirac:0.1 eV", charge=0.0, scf_algorithm=None): """ Returns a :class:`AbinitInput` for a structural relaxation. The first dataset optmizes the atomic positions at fixed unit cell. The second datasets optimizes both ions and unit cell parameters. Args: structure: :class:`Structure` object. pseudos: List of filenames or list of :class:`Pseudo` objects or :class:`PseudoTable` object. kppa: Defines the sampling used for the Brillouin zone. nband: Number of bands included in the SCF run. accuracy: Accuracy of the calculation. spin_mode: Spin polarization. smearing: Smearing technique. charge: Electronic charge added to the unit cell. scf_algorithm: Algorithm used for solving of the SCF cycle. """ structure = Structure.as_structure(structure) multi = MultiDataset(structure, pseudos, ndtset=2) # Set the cutoff energies. multi.set_vars(_find_ecut_pawecutdg(ecut, pawecutdg, multi.pseudos)) kppa = _DEFAULTS.get("kppa") if kppa is None else kppa ksampling = aobj.KSampling.automatic_density(structure, kppa, chksymbreak=0) electrons = aobj.Electrons(spin_mode=spin_mode, smearing=smearing, algorithm=scf_algorithm, charge=charge, nband=nband, fband=None) if electrons.nband is None: electrons.nband = _find_scf_nband(structure, multi.pseudos, electrons) ion_relax = aobj.RelaxationMethod.atoms_only(atoms_constraints=None) ioncell_relax = aobj.RelaxationMethod.atoms_and_cell( atoms_constraints=None) multi.set_vars(electrons.to_abivars()) multi.set_vars(ksampling.to_abivars()) multi[0].set_vars(ion_relax.to_abivars()) multi[0].set_vars(_stopping_criterion("relax", accuracy)) multi[1].set_vars(ioncell_relax.to_abivars()) multi[1].set_vars(_stopping_criterion("relax", accuracy)) return multi
def add_eos_tasks(self): """ Read the optimized structure from the netcdf file and add to self a new a new list of ScfTask for the computation of the EOS with the GBRV parameters. """ self.history.info("Building EOS tasks") # Get the relaxed structure. self.relaxed_structure = relaxed_structure = self.relax_task.get_final_structure() # GBRV use nine points from -1% to 1% of the initial guess and fitting the results to a parabola. # Note that it's not clear to me if they change the volume or the lattice parameter! self.volumes = relaxed_structure.volume * np.arange(99, 101.25, 0.25) / 100. for vol in self.volumes: new_lattice = relaxed_structure.lattice.scale(vol) new_structure = Structure(new_lattice, relaxed_structure.species, relaxed_structure.frac_coords) # Add ecutsm extra = self.extra_abivars.copy() extra["ecutsm"] = 0.5 scf_input = abilab.AbinitInput(new_structure, self.dojo_pseudo) scf_input.add_abiobjects(self.ksampling, self.spin_mode, self.smearing) scf_input.set_vars(extra) # Register new task self.register_scf_task(scf_input) # Allocate new tasks and update the pickle database. self.flow.allocate() self.flow.build_and_pickle_dump()
def abifile_subclass_from_filename(filename): from abipy.iotools.files import AbinitFile, AbinitLogFile, AbinitOutputFile from abipy.electrons import SIGRES_File, GSR_File, MDF_File from abipy.waves import WFK_File #from abipy.phonons import PHDOS_File, PHBST_File ext2ncfile = { "SIGRES.nc": SIGRES_File, "WFK-etsf.nc": WFK_File, "MDF.nc" : MDF_File, "GSR.nc": GSR_File #"PHDOS.nc": PHDOS_File, #"PHBST.nc": PHBST_File, } #if filename.endswith(".abi"): # return AbinitInputFile if filename.endswith(".abo"): return AbinitOutputFile if filename.endswith(".log"): return AbinitLogFile # CIF files. if filename.endswith(".cif"): from abipy.core.structure import Structure return Structure.from_file(filename) ext = filename.split("_")[-1] try: return ext2ncfile[ext] except KeyError: raise KeyError("No class has been registered for extension %s" % ext)
def structure(self): kwargs = {} if "angdeg" in self: assert "rprim" not in self raise NotImplementedError("angdeg") #kwargs["angdeg"] = else: # Handle structure specified with rprim. kwargs["rprim"] = str2array_bohr(self.get("rprim", "1.0 0 0 0 1 0 0 0 1")) # Default value for acell acell = str2array_bohr(self.get("acell", "1.0 1.0 1.0")) check = {k: 1 for k in ("xred", "xcart", "xangst") if k in self} if len(check) != 1: raise ValueError("Atomic positions are not specified correctly:\n%s" % str(check)) if "xred" in self: kwargs["xred"] = np.fromstring(self["xred"], sep=" ") elif "xcart" in self: kwargs["xcart"] = str2array_bohr(self["xcart"]) elif "xangst" in self: kwargs["xangst"] = np.fromstring(self["xangst"], sep=" ") return Structure.from_abivars( acell=acell, znucl=str2array(self["znucl"]), typat=str2array(self["typat"]), **kwargs )
def structure(self): structure = Structure.from_abivars(**self.header) # Add Spacegroup (needed in guessed_ngkpt) # FIXME: has_timerev is always True spgid, has_timerev, h = 0, True, self.header structure.set_spacegroup(SpaceGroup(spgid, h.symrel, h.tnons, h.symafm, has_timerev)) return structure
def work_for_pseudo(self, pseudo, accuracy="normal", kppa=6750, ecut=None, pawecutdg=None, toldfe=1.e-9, smearing="fermi_dirac:0.1 eV", workdir=None, manager=None, **kwargs): """ Returns a :class:`Work` object from the given pseudopotential. Args: kwargs: Extra variables passed to Abinit. .. note:: 0.001 Rydberg is the value used with WIEN2K """ pseudo = Pseudo.as_pseudo(pseudo) symbol = pseudo.symbol if pseudo.ispaw and pawecutdg is None: raise ValueError("pawecutdg must be specified for PAW calculations.") try: cif_path = self.get_cif_path(symbol) except Exception as exc: raise self.Error(str(exc)) # Include spin polarization for O, Cr and Mn (antiferromagnetic) # and Fe, Co, and Ni (ferromagnetic). # antiferromagnetic Cr, O # ferrimagnetic Mn spin_mode = "unpolarized" if symbol in ["Fe", "Co", "Ni"]: spin_mode = "polarized" if symbol == "Fe": kwargs['spinat'] = 2 * [(0, 0, 2.3)] if symbol == "Co": kwargs['spinat'] = 2 * [(0, 0, 1.2)] if symbol == "Ni": kwargs['spinat'] = 4 * [(0, 0, 0.6)] if symbol in ["O", "Cr", "Mn"]: spin_mode = "afm" if symbol == 'O': kwargs['spinat'] = [(0, 0, 1.5), (0, 0, 1.5), (0, 0, -1.5), (0, 0, -1.5)] elif symbol == 'Cr': kwargs['spinat'] = [(0, 0, 1.5), (0, 0, -1.5)] elif symbol == 'Mn': kwargs['spinat'] = [(0, 0, 2.0), (0, 0, 1.9), (0, 0, -2.0), (0, 0, -1.9)] # DO NOT CHANGE THE STRUCTURE REPORTED IN THE CIF FILE. structure = Structure.from_file(cif_path, primitive=False) # Magnetic elements: # Start from previous SCF run to avoid getting trapped in local minima connect = symbol in ("Fe", "Co", "Ni", "Cr", "Mn", "O", "Zn", "Cu") return DeltaFactorWork( structure, pseudo, kppa, connect, spin_mode=spin_mode, toldfe=toldfe, smearing=smearing, accuracy=accuracy, ecut=ecut, pawecutdg=pawecutdg, ecutsm=0.5, workdir=workdir, manager=manager, **kwargs)
def structure(self): # Get lattice. kwargs = {} if "angdeg" in self: if "rprim" in self: raise ValueError("rprim and angdeg cannot be used together!") angdeg = str2array(self["angdeg"]) angdeg.shape = (3) kwargs["angdeg"] = angdeg else: # Handle structure specified with rprim. kwargs["rprim"] = str2array_bohr(self.get("rprim", "1.0 0 0 0 1 0 0 0 1")) # Default value for acell. acell = str2array_bohr(self.get("acell", "1.0 1.0 1.0")) # Get important dimensions. ntypat = int(self.get("ntypat", 1)) natom = int(self.get("natom", 1)) # znucl(npsp) znucl = self["znucl"] if znucl.startswith("*"): i = znucl.find("*") znucl_size = natom if "npsp" not in self else int(self["npsp"]) znucl = znucl_size * [float(znucl[i+1:])] else: znucl = str2array(self["znucl"]) # v67mbpt/Input/t12.in typat = self["typat"] if typat.startswith("*"): i = typat.find("*") typat = np.array(natom * [int(typat[i+1:])], dtype=int) else: typat = str2array(self["typat"], dtype=int) # Extract atomic positions. # Select first natom entries (needed if multidatasets with different natom) # # v3/Input/t05.in typat = typat[:natom] for k in ("xred", "xcart", "xangst"): toarray = str2array_bohr if k == "xcart" else str2array if k in self: arr = np.reshape(toarray(self[k]), (-1, 3)) kwargs[k] = arr[:natom] break else: raise ValueError("xred|xcart|xangst must be given in input") try: return Structure.from_abivars(acell=acell, znucl=znucl, typat=typat, **kwargs) except Exception as exc: print("Wrong inputs passed to Structure.from_abivars:") print(" acell", acell) print(" znucl", znucl) print(" typat", typat) print(" kwargs", kwargs) raise exc
def structure(self): coords = [] coords.append([0, 0, 0]) coords.append([0.75, 0.5, 0.75]) lattice = Lattice([[3.8401979337, 0.00, 0.00], [1.9200989668, 3.3257101909, 0.00], [0.00, -2.2171384943, 3.1355090603]]) return Structure(lattice, ["Si", "Si"], coords)
def set_structure(self, structure, dtset=0): """Set the :class:`Structure` object for the specified dtset.""" structure = Structure.as_structure(structure) if dtset is None: dtset = slice(self.ndtset + 1) for idt in self._dtset2range(dtset): self[idt].set_structure(structure)
def set_structure(self, structure, dtset=0): """Set the :class:`Structure` object for the specified dtset.""" structure = Structure.as_structure(structure) if dtset is None: dtset = slice(self.ndtset+1) for idt in self._dtset2range(dtset): self[idt].set_structure(structure)
def work_for_pseudo(self, pseudo, kppa=3000, maxene=250, ecut=None, pawecutdg=None, spin_mode="unpolarized", include_soc=False, tolwfr=1.e-12, smearing="fermi_dirac:0.1 eV", workdir=None, manager=None, **kwargs): """ Returns a :class:`Work` object from the given pseudopotential. Args: pseudo: :class:`Pseudo` object. kppa: Number of k-points per reciprocal atom. ecut: Cutoff energy in Hartree pawecutdg: Cutoff energy of the fine grid (PAW only) spin_mode: Spin polarization option tolwfr: Tolerance on the residuals. smearing: Smearing technique. workdir: Working directory. manager: :class:`TaskManager` object. kwargs: Extra variables passed to Abinit. """ if pseudo.ispaw and pawecutdg is None: raise ValueError( "pawecutdg must be specified for PAW calculations.") if pseudo.xc != self._dfdb.xc: raise ValueError( "Pseudo xc differs from the XC used to instantiate the factory\n" "Pseudo: %s, Database: %s" % (pseudo.xc, self._dfdb.xc)) try: cif_path = self.get_cif_path(pseudo.symbol) except Exception as exc: raise self.Error(str(exc)) # DO NOT CHANGE THE STRUCTURE REPORTED IN THE CIF FILE. structure = Structure.from_file(cif_path, primitive=False) return GhostsWork(structure, pseudo, kppa, maxene, spin_mode=spin_mode, include_soc=include_soc, tolwfr=tolwfr, smearing=smearing, ecut=ecut, pawecutdg=pawecutdg, ecutsm=0.5, workdir=workdir, manager=manager, **kwargs)
def from_gs_input(cls, gsinp, voldelta, scdims, phonopy_kwargs=None, displ_kwargs=None): """ Build the work from an :class:`AbinitInput` object representing a GS calculations. Args: gsinp: :class:`AbinitInput` object representing a GS calculation in the initial unit cell. voldelta: Absolute increment for unit cell volume. The three volumes are: [v0 - voldelta, v0, v0 + voldelta] where v0 is taken from gsinp.structure. scdims: Number of unit cell replicas along the three reduced directions. phonopy_kwargs: (Optional) dictionary with arguments passed to Phonopy constructor. displ_kwargs: (Optional) dictionary with arguments passed to generate_displacements. Return: `PhonopyGruneisenWork` instance. """ new = cls() # Save arguments that will be used to call phonopy for creating # the supercells with the displacements once the three volumes have been relaxed. new.scdims = np.array(scdims) if new.scdims.shape != (3, ): raise ValueError("Expecting 3 int in scdims but got %s" % str(new.scdims)) new.phonopy_kwargs = phonopy_kwargs if phonopy_kwargs is not None else {} new.displ_kwargs = displ_kwargs if displ_kwargs is not None else {} # Build three tasks for structural optimization at constant volume. v0 = gsinp.structure.volume if voldelta <= 0: raise ValueError("voldelta must be > 0 but got %s" % voldelta) volumes = [v0 - voldelta, v0, v0 + voldelta] if any(v <= 0 for v in volumes): raise ValueError("volumes must be > 0 but got %s" % str(volumes)) for vol in volumes: # Build new structure new_lattice = gsinp.structure.lattice.scale(vol) new_structure = Structure(new_lattice, gsinp.structure.species, gsinp.structure.frac_coords) new_input = gsinp.new_with_structure(new_structure) # Set variables for structural optimization at constant volume. new_input.pop_tolerances() new_input.set_vars(optcell=3, ionmov=3, tolvrs=1e-10, toldff=1.e-6) new_input.set_vars_ifnotin(ecutsm=0.5, dilatmx=1.05) new.register_relax_task(new_input) return new
def structure_from_atoms(atoms): """ Convert a phonopy Atoms object into a pymatgen Structure. """ return Structure(lattice=atoms.cell, species=atoms.symbols, coords=atoms.scaled_positions, validate_proximity=False, to_unit_cell=False, coords_are_cartesian=False, site_properties=None)
def work_for_pseudo(self, pseudo, kppa=6750, ecut=None, pawecutdg=None, toldfe=1.e-9, smearing="fermi_dirac:0.1 eV", include_soc=False, workdir=None, manager=None, **kwargs): """ Returns a :class:`Work` object from the given pseudopotential. Args: pseudo: :class:`Pseudo` object. kppa: kpoint per reciprocal atom ecut: Cutoff energy in Hartree pawecutdg: Cutoff energy of the fine grid (PAW only) toldfe: Tolerance on the energy (Ha) smearing: Smearing technique. include_soc: True if pseudo has SO contributions and calculation should be done with nspinor=2 workdir: String specifing the working directory. manager: :class:`TaskManager` responsible for the submission of the tasks. kwargs: Extra variables passed to Abinit. .. note:: 0.001 Rydberg is the value used with WIEN2K """ symbol = pseudo.symbol if pseudo.ispaw and pawecutdg is None: raise ValueError("pawecutdg must be specified for PAW calculations.") if pseudo.xc != self._dfdb.xc: raise ValueError( "Pseudo xc differs from the XC used to instantiate the factory\n" "Pseudo: %s, Database: %s" % (pseudo.xc, self._dfdb.xc)) try: cif_path = self.get_cif_path(symbol) except Exception as exc: raise self.Error(str(exc)) # WARNING: DO NOT CHANGE THE STRUCTURE REPORTED IN THE CIF FILE. structure = Structure.from_file(cif_path, primitive=False) # Include spin polarization and initial spinat for particular elements # TODO: Not sure spinat is ok if LDA. kwargs["spinat"], spin_mode = self._dfdb.spinat_spinmode_for_symbol(symbol) if include_soc: spin_mode = "spinor" # This is needed for LDA if symbol in ("O", "Mn"): print("Got Oxygen or Mn") spin_mode = "polarized" # Magnetic elements: # Start from previous SCF run to avoid getting trapped in local minima connect = symbol in ("Fe", "Co", "Ni", "Cr", "Mn", "O", "Zn", "Cu") return DeltaFactorWork( structure, pseudo, kppa, connect, spin_mode=spin_mode, include_soc=include_soc, toldfe=toldfe, smearing=smearing, ecut=ecut, pawecutdg=pawecutdg, ecutsm=0.5, workdir=workdir, manager=manager, **kwargs)
def structure(self): # Get lattice. kwargs = {} if "angdeg" in self: if "rprim" in self: raise ValueError("rprim and angdeg cannot be used together!") angdeg = str2array(self["angdeg"]) angdeg.shape = (3) kwargs["angdeg"] = angdeg else: # Handle structure specified with rprim. kwargs["rprim"] = str2array_bohr(self.get("rprim", "1.0 0 0 0 1 0 0 0 1")) # Default value for acell. acell = str2array_bohr(self.get("acell", "1.0 1.0 1.0")) # Get important dimensions. ntypat = int(self.get("ntypat", 1)) natom = int(self.get("natom", 1)) # znucl(npsp) znucl = self["znucl"] if znucl.startswith("*"): i = znucl.find("*") znucl_size = natom if "npsp" not in self else int(self["npsp"]) znucl = znucl_size * [float(znucl[i+1:])] else: znucl = str2array(self["znucl"]) # v67mbpt/Input/t12.in typat = self["typat"] if typat.startswith("*"): i = typat.find("*") typat = np.array(natom * [int(typat[i+1:])], dtype=int) else: typat = str2array(self["typat"], dtype=int) # Extract atomic positions. # Select first natom entries (needed if multidatasets with different natom) # # v3/Input/t05.in typat = typat[:natom] for k in ("xred", "xcart", "xangst"): toarray = str2array_bohr if k == "xcart" else str2array if k in self: arr = np.reshape(toarray(self[k]), (-1, 3)) kwargs[k] = arr[:natom] break else: raise ValueError("xred|xcart|xangst must be given in input") try: return Structure.from_abivars(acell=acell, znucl=znucl, typat=typat, **kwargs) except Exception as exc: print("Wrong inputs passed to Structure.from_abivars:") print("acell:", acell, "znucl:", znucl, "typat:", typat, "kwargs:", kwargs, sep="\n") raise exc
def work_for_pseudo(self, pseudo, **kwargs): """ Create a :class:`Flow` for phonon calculations: 1) One workflow for the GS run. 2) nqpt workflows for phonon calculations. Each workflow contains nirred tasks where nirred is the number of irreducible phonon perturbations for that particular q-point. the kwargs are passed to scf_hp_inputs """ try: qpt = kwargs['qpt'] except IndexError: raise ValueError('A phonon test needs to specify a qpoint.') kwargs.pop('accuracy') pseudo = Pseudo.as_pseudo(pseudo) structure_or_cif = self.get_cif_path(pseudo.symbol) if not isinstance(structure_or_cif, Structure): # Assume CIF file structure = Structure.from_file(structure_or_cif, primitive=False) else: structure = structure_or_cif nat = len(structure) report = pseudo.read_dojo_report() ecut_str = '%.1f' % kwargs['ecut'] #print(ecut_str) #print(report['deltafactor'][float(ecut_str)].keys()) try: v0 = nat * report['deltafactor'][ecut_str]['v0'] except KeyError: try: v0 = nat * report['deltafactor'][float(ecut_str)]['v0'] except KeyError: # the df calculation at this ecut is not done already so the phonon task can not be created return None structure.scale_lattice(v0) all_inps = self.scf_ph_inputs(pseudos=[pseudo], structure=structure, **kwargs) scf_input, ph_inputs = all_inps[0], all_inps[1:] work = build_oneshot_phononwork(scf_input=scf_input, ph_inputs=ph_inputs, work_class=PhononDojoWork) #print('after build_oneshot_phonon') #print(work) work.set_dojo_trial(qpt) #print(scf_input.keys()) work.ecut = scf_input['ecut'] work._pseudo = pseudo return work
def from_scf_input(cls, scf_input, npoints=4, deltap_vol=0.25, ecutsm=0.5, move_atoms=True, manager=None): """ Build a EosWork from an AbinitInput representing a SCF-GS calculation. Args: scf_input: AbinitInput for SCF-GS used as template to generate the other inputs. npoints: Number of volumes generated on the right (left) of the equilibrium volume The total number of points is therefore 2 * n + 1. deltap_vol: Step of the linear mesh given in relative percentage of the equilibrium volume The step is thus: v0 * deltap_vol / 100. ecutsm: Value of ecutsm input variable. If `scf_input` does not provide ecutsm, this value will be used else the vale in `scf_input`. move_atoms: If True, a structural relaxation of ions is performed for each volume This is needed if the atomic positions are non fixed by symmetry. manager: TaskManager instance. Use default if None. Return: EosWork instance. """ new_work = cls(manager=manager) structure = scf_input.structure lattice_type = structure.spget_lattice_type() assert lattice_type is not None dvol = structure.volume * deltap_vol / 100 v0 = structure.volume - dvol * npoints new_work.input_volumes = [v0 + ipt * dvol for ipt in range(2 * npoints + 1)] if "ecutsm" not in scf_input: print("Input does not define ecutsm input variable.\n", "A default value of %s will be added to all the EOS inputs" % ecutsm) for vol in new_work.input_volumes: # Build structure with new volume and generate new input. new_lattice = structure.lattice.scale(vol) new_structure = Structure(new_lattice, structure.species, structure.frac_coords) new_input = scf_input.new_with_structure(new_structure) # Add ecutsm if not already present. new_input.set_vars_ifnotin(ecutsm=ecutsm) if lattice_type == "cubic" and not move_atoms: # Perform GS calculations without moving atoms, cells do not need to be relaxed. new_input.pop_vars(["ionmov", "optcell", "ntime"]) new_work.register_scf_task(new_input) else: # Constant-volume optimization of cell geometry + atoms. # (modify acell and rprim under constraint - normalize the vectors of rprim to generate the acell) # In principle one could take into account the symmetry of the lattice... new_input.set_vars_ifnotin(ionmov=2, ntime=50, optcell=3, dilatmx=1.05) new_work.register_relax_task(new_input) return new_work
def __init__(self, entries): self.entries = entries from abipy.core.structure import Structure for e in entries: e.structure = Structure.as_structure(e.structure) self.structures = [e.structure for e in entries] self.mpids = [e.entry_id for e in entries] # Create phase diagram. from pymatgen.analysis.phase_diagram import PhaseDiagram self.phasediagram = PhaseDiagram(self.entries)
def _generate_inputdata(self, parameters: orm.Dict, pseudos, structure: orm.StructureData, kpoints: orm.KpointsData) -> ty.Tuple[str, list]: """Generate the input file content and list of pseudopotential files to copy. :param parameters: input parameters Dict :param pseudos: pseudopotential input namespace :param structure: input structure :param kpoints: input kpoints :returns: input file content, pseudopotential copy list """ local_copy_pseudo_list = [] # abipy has its own subclass of Pymatgen's `Structure`, so we use that pmg_structure = structure.get_pymatgen() abi_structure = AbiStructure.as_structure(pmg_structure) abi_structure = abi_structure.abi_sanitize(primitive=True) for kind in structure.get_kind_names(): pseudo = pseudos[kind] local_copy_pseudo_list.append((pseudo.uuid, pseudo.filename, f'{self._PSEUDO_SUBFOLDER}{pseudo.filename}')) # Pseudopotentials _must_ be listed in the same order as 'znucl' in the input file. # So, we need to get 'znucl' as abipy will write it then construct the appropriate 'pseudos' string. znucl = structure_to_abivars(abi_structure)['znucl'] ordered_pseudo_filenames = [pseudos[constants.elements[Z]['symbol']].filename for Z in znucl] pseudo_parameters = { 'pseudos': '"' + ', '.join(ordered_pseudo_filenames) + '"', 'pp_dirpath': f'"{self._PSEUDO_SUBFOLDER}"' } input_parameters = parameters.get_dict() # k-points are provided to abipy separately from the main input parameters, so we pop out # parameters related to the k-points shiftk = input_parameters.pop('shiftk', [0.0, 0.0, 0.0]) # NOTE: currently, only k-point mesh are supported, not k-point paths kpoints_mesh = kpoints.get_kpoints_mesh()[0] # use abipy to write the input file input_parameters = {**input_parameters, **pseudo_parameters} # give abipy the HGH_TABLE only so it won't error, but don't actually print these to file abi_input = AbinitInput( structure=abi_structure, pseudos=HGH_TABLE, abi_kwargs=input_parameters ) abi_input.set_kmesh( ngkpt=kpoints_mesh, shiftk=shiftk ) return abi_input.to_string(with_pseudos=False), local_copy_pseudo_list
def from_gs_input(cls, gs_inp, voldelta, ngqpt, tolerance=None, with_becs=False, ddk_tolerance=None, workdir=None, manager=None): """ Build the work from an |AbinitInput| representing a GS calculations. Args: gs_inp: |AbinitInput| representing a GS calculation in the initial unit cell. voldelta: Absolute increment for unit cell volume. The three volumes are: [v0 - voldelta, v0, v0 + voldelta] where v0 is taken from gs_inp.structure. ngqpt: three integers defining the q-mesh for phonon calculations. tolerance: dict {"varname": value} with the tolerance to be used in the phonon run. None to use AbiPy default. with_becs: Activate calculation of Electric field and Born effective charges. ddk_tolerance: dict {"varname": value} with the tolerance used in the DDK run if with_becs. None to use AbiPy default. """ new = cls(workdir=workdir, manager=manager) new.ngqpt = np.reshape(ngqpt, (3,)) new.with_becs = with_becs new.ddk_tolerance = ddk_tolerance new.tolerance = tolerance if any(gs_inp["ngkpt"] % new.ngqpt != 0): raise ValueError("Kmesh and Qmesh must be commensurate.\nGot ngkpt: `%s`\nand ngqpt: `%s`" % ( str(gs_inp["ngkpt"]), str(new.ngqpt))) # Build three tasks for structural optimization at constant volume. v0 = gs_inp.structure.volume if voldelta <= 0: raise ValueError("voldelta must be > 0 but got %s" % voldelta) volumes = [v0 - voldelta, v0, v0 + voldelta] if any(v <= 0 for v in volumes): raise ValueError("volumes must be > 0 but got %s" % str(volumes)) # Keep a copy of the GS input that will be used to generate the Phonon Works new.gs_inp = gs_inp.deepcopy() new.relax_tasks = [] for vol in volumes: # Build new structure new_lattice = gs_inp.structure.lattice.scale(vol) new_structure = Structure(new_lattice, gs_inp.structure.species, gs_inp.structure.frac_coords) new_input = gs_inp.new_with_structure(new_structure) # Set variables for structural optimization at constant volume. new_input.pop_tolerances() new_input.set_vars(optcell=3, ionmov=3, tolvrs=1e-10, toldff=1.e-6) new_input.set_vars_ifnotin(ecutsm=0.5, dilatmx=1.05) t = new.register_relax_task(new_input) new.relax_tasks.append(t) return new
def ion_ioncell_relax_input(structure, pseudos, kppa=None, nband=None, ecut=None, pawecutdg=None, accuracy="normal", spin_mode="polarized", smearing="fermi_dirac:0.1 eV", charge=0.0, scf_algorithm=None): """ Returns a :class:`AbinitInput` for a structural relaxation. The first dataset optmizes the atomic positions at fixed unit cell. The second datasets optimizes both ions and unit cell parameters. Args: structure: :class:`Structure` object. pseudos: List of filenames or list of :class:`Pseudo` objects or :class:`PseudoTable` object. kppa: Defines the sampling used for the Brillouin zone. nband: Number of bands included in the SCF run. accuracy: Accuracy of the calculation. spin_mode: Spin polarization. smearing: Smearing technique. charge: Electronic charge added to the unit cell. scf_algorithm: Algorithm used for solving of the SCF cycle. """ structure = Structure.as_structure(structure) multi = MultiDataset(structure, pseudos, ndtset=2) # Set the cutoff energies. multi.set_vars(_find_ecut_pawecutdg(ecut, pawecutdg, multi.pseudos)) kppa = _DEFAULTS.get("kppa") if kppa is None else kppa ksampling = aobj.KSampling.automatic_density(structure, kppa, chksymbreak=0) electrons = aobj.Electrons(spin_mode=spin_mode, smearing=smearing, algorithm=scf_algorithm, charge=charge, nband=nband, fband=None) if spin_mode=="polarized": spinat_dict = multi[0].set_autospinat() multi[1].set_vars(spinat_dict) if electrons.nband is None: electrons.nband = _find_scf_nband(structure, multi.pseudos, electrons, multi[0].get('spinat', None)) ion_relax = aobj.RelaxationMethod.atoms_only(atoms_constraints=None) ioncell_relax = aobj.RelaxationMethod.atoms_and_cell(atoms_constraints=None) multi.set_vars(electrons.to_abivars()) multi.set_vars(ksampling.to_abivars()) multi[0].set_vars(ion_relax.to_abivars()) multi[0].set_vars(_stopping_criterion("relax", accuracy)) multi[1].set_vars(ioncell_relax.to_abivars()) multi[1].set_vars(_stopping_criterion("relax", accuracy)) return multi
def cube_read_structure_mesh_data(file): with open(file, 'r') as fh: # The two first lines are comments for ii in range(2): fh.readline() # Number of atoms natoms = int(fh.readline().split()[0]) # The next three lines give the mesh and the vectors sp = fh.readline().split() nx = int(sp[0]) dvx = np.array([float(sp[ii]) for ii in range(1, 4)]) * bohr_to_angstrom sp = fh.readline().split() ny = int(sp[0]) dvy = np.array([float(sp[ii]) for ii in range(1, 4)]) * bohr_to_angstrom sp = fh.readline().split() nz = int(sp[0]) dvz = np.array([float(sp[ii]) for ii in range(1, 4)]) * bohr_to_angstrom uc_matrix = np.array([nx * dvx, ny * dvy, nz * dvz]) sites = [] lattice = Lattice(uc_matrix) for ii in range(natoms): sp = fh.readline().split() cc = np.array([float(sp[ii]) for ii in range(2, 5)]) * bohr_to_angstrom sites.append( PeriodicSite(int(sp[0]), coords=cc, lattice=lattice, to_unit_cell=False, coords_are_cartesian=True)) data = np.zeros((nx, ny, nz)) ii = 0 for line in fh: for val in line.split(): data[ii // (ny * nz), (ii // nz) % ny, ii % nz] = float(val) ii += 1 data = data / (bohr_to_angstrom**3) if ii != nx * ny * nz: raise ValueError('Wrong number of data points ...') from abipy.core.structure import Structure structure = Structure.from_sites(sites=sites) from abipy.core.mesh3d import Mesh3D mesh = Mesh3D(shape=[nx, ny, nz], vectors=uc_matrix) return structure, mesh, data
def __init__(self, filepath): super(DdbFile, self).__init__(filepath) self._header = self._parse_header() self._structure = Structure.from_abivars(**self.header) # Add Spacegroup (needed in guessed_ngkpt) # FIXME: has_timerev is always True spgid, has_timerev, h = 0, True, self.header self._structure.set_spacegroup(SpaceGroup(spgid, h.symrel, h.tnons, h.symafm, has_timerev)) frac_coords = self._read_qpoints() self._qpoints = KpointList(self.structure.reciprocal_lattice, frac_coords, weights=None, names=None) # Guess q-mesh self._guessed_ngqpt = self._guess_ngqpt()
def scf_for_phonons(structure, pseudos, kppa=None, ecut=None, pawecutdg=None, nband=None, accuracy="normal", spin_mode="polarized", smearing="fermi_dirac:0.1 eV", charge=0.0, scf_algorithm=None, shift_mode="Symmetric"): abiinput = scf_input(structure=structure, pseudos=pseudos, kppa=kppa, ecut=ecut, pawecutdg=pawecutdg, nband=nband, accuracy=accuracy, spin_mode=spin_mode, smearing=smearing, charge=charge, scf_algorithm=scf_algorithm, shift_mode=shift_mode) # set symmetrized k-point if shift_mode[0].lower() == 's': # need to convert to abipy structure to get the calc_shiftk method structure = Structure.from_sites(structure) shiftk = structure.calc_shiftk() abiinput.set_vars(shiftk=shiftk, nshiftk=len(shiftk)) # enforce symmetries and add a buffer of bands to ease convergence with tolwfr abiinput.set_vars(chksymbreak=1, nbdbuf=4, tolwfr=1.e-22) return abiinput
def add_task_with_ecut(self, ecut): """Register a new task with cutoff energy ecut.""" # One atom in a box of lenghts acell. inp = abilab.AbinitInput(structure=Structure.boxed_atom(self.pseudo, acell=self.acell), pseudos=self.pseudo) # Gamma-only sampling. inp.add_abiobjects(self.spin_mode, self.smearing, KSampling.gamma_only()) inp.set_vars( ecut=ecut, toldfe=self.toldfe, prtwf=1, ) self.ecuts.append(ecut) self.register_scf_task(inp)
def display_structure(obj, **kwargs): """ Use Jsmol to display a structure in the jupyter notebook. Requires `nbjsmol` notebook extension installed on the local machine. Install it with `pip install nbjsmol`. See also https://github.com/gmatteo/nbjsmol. Args: obj: Structure object or file with a structure or python object with a `structure` attribute. kwargs: Keyword arguments passed to `nbjsmol_display` """ try: from nbjsmol import nbjsmol_display except ImportError as exc: raise ImportError( str(exc) + "\ndisplay structure requires nbjsmol package\n." "Install it with `pip install nbjsmol.`\n" "See also https://github.com/gmatteo/nbjsmol.") # Cast to structure, get string with cif data and pass it to nbjsmol. structure = Structure.as_structure(obj) return nbjsmol_display(structure.to(fmt="cif"), ext=".cif", **kwargs)
def display_structure(obj, **kwargs): """ Use Jsmol to display a structure in the jupyter notebook. Requires `nbjsmol` notebook extension installed on the local machine. Install it with `pip install nbjsmol`. See also https://github.com/gmatteo/nbjsmol. Args: obj: Structure object or file with a structure or python object with a `structure` attribute. kwargs: Keyword arguments passed to `nbjsmol_display` """ try: from nbjsmol import nbjsmol_display except ImportError as exc: raise ImportError(str(exc) + "\ndisplay structure requires nbjsmol package\n." "Install it with `pip install nbjsmol.`\n" "See also https://github.com/gmatteo/nbjsmol.") # Cast to structure, get string with cif data and pass it to nbjsmol. structure = Structure.as_structure(obj) return nbjsmol_display(structure.to(fmt="cif"), ext=".cif", **kwargs)
def cube_read_structure_mesh_data(file): with open(file, 'r') as fh: # The two first lines are comments for ii in range(2): fh.readline() # Number of atoms natoms = int(fh.readline().split()[0]) # The next three lines give the mesh and the vectors sp = fh.readline().split() nx = int(sp[0]) dvx = np.array([float(sp[ii]) for ii in range(1, 4)]) * bohr_to_angstrom sp = fh.readline().split() ny = int(sp[0]) dvy = np.array([float(sp[ii]) for ii in range(1, 4)]) * bohr_to_angstrom sp = fh.readline().split() nz = int(sp[0]) dvz = np.array([float(sp[ii]) for ii in range(1, 4)]) * bohr_to_angstrom uc_matrix = np.array([nx*dvx, ny*dvy, nz*dvz]) sites = [] lattice = Lattice(uc_matrix) for ii in range(natoms): sp = fh.readline().split() cc = np.array([float(sp[ii]) for ii in range(2, 5)]) * bohr_to_angstrom sites.append(PeriodicSite(int(sp[0]), coords=cc, lattice=lattice, to_unit_cell=False, coords_are_cartesian=True)) data = np.zeros((nx, ny, nz)) ii = 0 for line in fh: for val in line.split(): data[ii//(ny*nz), (ii//nz)%ny, ii%nz] = float(val) ii += 1 data = data / (bohr_to_angstrom ** 3) if ii != nx*ny*nz: raise ValueError('Wrong number of data points ...') from abipy.core.structure import Structure structure = Structure.from_sites(sites=sites) from abipy.core.mesh3d import Mesh3D mesh = Mesh3D(shape=[nx, ny, nz], vectors=uc_matrix) return structure, mesh, data
def half_heusler(a, species): # fcc lattice with 3 atoms as basis # prototype: AgAlGe # See also http://www.cryst.ehu.es/cgi-bin/cryst/programs/nph-wp-list?gnum=216 lattice = 0.5 * float(a) * np.array([0, 1, 1, 1, 0, 1, 1, 1, 0]) frac_coords = np.reshape( [ 0, 0, 0, # Ag 0.5, 0.5, 0.5, # Al 1 / 4, 1 / 4, 1 / 4, # Ge #3/4, 3/4, 3/4, # Z ], (3, 3)) return Structure(lattice, species, frac_coords, coords_are_cartesian=False)
def test_si(self): """Testing wyckoff positions for Si2""" si = Structure.from_file(abidata.cif_file("si.cif")) ss = si.site_symmetries repr(ss) str(ss) assert ss.to_string(verbose=2) df = ss.get_wyckoff_dataframe(verbose=2) self.assert_equal(np.array(df["xfrac"].values, dtype=float), [0, 0.25]) self.assert_equal(np.array(df["yfrac"].values, dtype=float), [0, 0.25]) self.assert_equal(np.array(df["zfrac"].values, dtype=float), [0, 0.25]) #0 -43m (#31) nsym:24 0 0 0 #1 -43m (#31) nsym:24 0.250000000000000 0.250000000000000 0.250000000000000 df = ss.get_tensor_rank2_dataframe(verbose=2) ref = ["Tzz", "Tzz"] self.assert_equal(df["Txx"].values, ref) self.assert_equal(df["Tyy"].values, ref) ref = ["-Tzz/3", "-Tzz/3"] self.assert_equal(df["Txy"].values, ref) self.assert_equal(df["Txz"].values, ref) self.assert_equal(df["Tyz"].values, ref)
def work_for_pseudo(self, pseudo, kppa=3000, maxene=250, ecut=None, pawecutdg=None, spin_mode="unpolarized", include_soc=False, tolwfr=1.e-12, smearing="fermi_dirac:0.1 eV", workdir=None, manager=None, **kwargs): """ Returns a :class:`Work` object from the given pseudopotential. Args: pseudo: :class:`Pseudo` object. kppa: Number of k-points per reciprocal atom. ecut: Cutoff energy in Hartree pawecutdg: Cutoff energy of the fine grid (PAW only) spin_mode: Spin polarization option tolwfr: Tolerance on the residuals. smearing: Smearing technique. workdir: Working directory. manager: :class:`TaskManager` object. kwargs: Extra variables passed to Abinit. """ if pseudo.ispaw and pawecutdg is None: raise ValueError("pawecutdg must be specified for PAW calculations.") if pseudo.xc != self._dfdb.xc: raise ValueError( "Pseudo xc differs from the XC used to instantiate the factory\n" "Pseudo: %s, Database: %s" % (pseudo.xc, self._dfdb.xc)) try: cif_path = self.get_cif_path(pseudo.symbol) except Exception as exc: raise self.Error(str(exc)) # DO NOT CHANGE THE STRUCTURE REPORTED IN THE CIF FILE. structure = Structure.from_file(cif_path, primitive=False) return GhostsWork( structure, pseudo, kppa, maxene, spin_mode=spin_mode, include_soc=include_soc, tolwfr=tolwfr, smearing=smearing, ecut=ecut, pawecutdg=pawecutdg, ecutsm=0.5, workdir=workdir, manager=manager, **kwargs)
def AbinitNscfTasks(structure, kpoints, ecut, nscf_bands, nscf_kpoints=None, **kwargs): from abipy.core.structure import Structure from abipy.abio.factories import scf_for_phonons from pymatgen.core.units import bohr_to_ang #extract pseudos pseudo_list = [] for atype, (mass, pseudo) in structure['atypes'].items(): pseudo_list.append(pseudo) pseudo_table = kwargs.pop("pseudo_table", pseudo_list) #create a PwInput file just to read the ibrav from structure qe_input = PwIn.from_structure_dict(structure) lattice, coords, species = qe_input.get_cell() lattice = [[col * bohr_to_ang for col in row] for row in lattice] structure = Structure(lattice, species, coords) #create an AbinitInput file from structure spin_mode = kwargs.pop('spin_mode', 'unpolarized') smearing = kwargs.pop('smearing', 'nosmearing') inp = scf_for_phonons(structure, pseudo_table, spin_mode=spin_mode, smearing=smearing, ecut=ecut / 2) return AbinitNscfTasksFromAbinitInput(inp, kpoints, ecut, nscf_bands, nscf_kpoints=nscf_kpoints, **kwargs)
def get_abistructure_from_abiref(basename): """Return an Abipy |Structure| from the basename of one of the reference files.""" from abipy.core.structure import Structure return Structure.as_structure(abidata.ref_file(basename))
def bse_with_mdf_inputs(structure, pseudos, scf_kppa, nscf_nband, nscf_ngkpt, nscf_shiftk, ecuteps, bs_loband, bs_nband, soenergy, mdf_epsinf, ecut=None, pawecutdg=None, exc_type="TDA", bs_algo="haydock", accuracy="normal", spin_mode="polarized", smearing="fermi_dirac:0.1 eV", charge=0.0, scf_algorithm=None): """ Returns a :class:`AbinitInput` object that performs a GS + NSCF + Bethe-Salpeter calculation. The self-energy corrections are approximated with the scissors operator. The screening in modeled with the model dielectric function. Args: structure: :class:`Structure` object. pseudos: List of filenames or list of :class:`Pseudo` objects or :class:`PseudoTable` object. scf_kppa: Defines the sampling used for the SCF run. nscf_nband: Number of bands included in the NSCF run. nscf_ngkpt: Divisions of the k-mesh used for the NSCF and the BSE run. nscf_shiftk: Shifts used for the NSCF and the BSE run. ecuteps: Cutoff energy [Ha] for the screening matrix. bs_loband: Index of the first occupied band included the e-h basis set (ABINIT convention i.e. first band starts at 1). Can be scalar or array of shape (nsppol,) bs_nband: Highest band idex used for the construction of the e-h basis set. soenergy: Scissor energy in Hartree. mdf_epsinf: Value of the macroscopic dielectric function used in expression for the model dielectric function. ecut: cutoff energy in Ha (if None, ecut is initialized from the pseudos according to accuracy) pawecutdg: cutoff energy in Ha for PAW double-grid (if None, pawecutdg is initialized from the pseudos according to accuracy) exc_type: Approximation used for the BSE Hamiltonian (Tamm-Dancoff or coupling). bs_algo: Algorith for the computatio of the macroscopic dielectric function. accuracy: Accuracy of the calculation. spin_mode: Spin polarization. smearing: Smearing technique. charge: Electronic charge added to the unit cell. scf_algorithm: Algorithm used for solving the SCF cycle. """ structure = Structure.as_structure(structure) multi = MultiDataset(structure, pseudos, ndtset=3) # Set the cutoff energies. d = _find_ecut_pawecutdg(ecut, pawecutdg, multi.pseudos) multi.set_vars(ecut=d.ecut, ecutwfn=d.ecut, pawecutdg=d.pawecutdg) # Ground-state scf_ksampling = aobj.KSampling.automatic_density(structure, scf_kppa, chksymbreak=0) scf_electrons = aobj.Electrons(spin_mode=spin_mode, smearing=smearing, algorithm=scf_algorithm, charge=charge, nband=None, fband=None) if scf_electrons.nband is None: scf_electrons.nband = _find_scf_nband(structure, multi.pseudos, scf_electrons) multi[0].set_vars(scf_ksampling.to_abivars()) multi[0].set_vars(scf_electrons.to_abivars()) multi[0].set_vars(_stopping_criterion("scf", accuracy)) # NSCF calculation with the randomly-shifted k-mesh. nscf_ksampling = aobj.KSampling.monkhorst(nscf_ngkpt, shiftk=nscf_shiftk, chksymbreak=0) nscf_electrons = aobj.Electrons(spin_mode=spin_mode, smearing=smearing, algorithm={"iscf": -2}, charge=charge, nband=nscf_nband, fband=None) multi[1].set_vars(nscf_ksampling.to_abivars()) multi[1].set_vars(nscf_electrons.to_abivars()) multi[1].set_vars(_stopping_criterion("nscf", accuracy)) # BSE calculation. exc_ham = aobj.ExcHamiltonian(bs_loband, bs_nband, soenergy, coulomb_mode="model_df", ecuteps=ecuteps, spin_mode=spin_mode, mdf_epsinf=mdf_epsinf, exc_type=exc_type, algo=bs_algo, bs_freq_mesh=None, with_lf=True, zcut=None) multi[2].set_vars(nscf_ksampling.to_abivars()) multi[2].set_vars(nscf_electrons.to_abivars()) multi[2].set_vars(exc_ham.to_abivars()) #multi[2].set_vars(_stopping_criterion("nscf", accuracy)) # TODO: Cannot use istwfk != 1. multi.set_vars(istwfk="*1") return multi
def _get_structure(self, obj): """Extract the structure from the input object.""" return Structure.as_structure(obj)
def structure(self): """Returns the :class:`Structure` associated to this dataset.""" # TODO: Avoid calling Structure.from_abivars, find a way to cache the object and invalidate it. return Structure.from_abivars(self.allvars)
def _parse_dims(self): """ Parse basic dimensions and get structure from the header of the file. """ self.version, self._structure, self.grid_size = None, None, None # Init dictionary with parameters. self.params_section = OrderedDict([ (s, OrderedDict()) for s in ("MAIN", "WANNIERISE", "PLOTTING", "DISENTANGLE") ]) params_done = False for iln, line in enumerate(self.lines): # Check for any warnings if 'Warning' in line: self.warnings.append(line) continue if "Time to read parameters" in line: params_done = True continue # Get release string. if "Release:" in line: i = line.find("Release:") self.version = line[i:].split()[1] continue # Parse lattice. if "Lattice Vectors" in line and self._structure is None: # Lattice Vectors (Ang) # a_1 0.000000 2.715473 2.715473 # a_2 2.715473 0.000000 2.715473 # a_3 2.715473 2.715473 0.000000 lattice = np.array([ list(map(float, self.lines[iln + j].split()[1:])) for j in range(1, 4) ]) continue # Parse atoms. if "| Site " in line and self._structure is None: # *----------------------------------------------------------------------------* # | Site Fractional Coordinate Cartesian Coordinate (Ang) | # +----------------------------------------------------------------------------+ # | Si 1 0.00000 0.00000 0.00000 | 0.00000 0.00000 0.00000 | # | Si 2 0.25000 0.25000 0.25000 | 1.35774 1.35774 1.35774 | # *----------------------------------------------------------------------------* frac_coords, species = [], [] i = iln + 2 while True: l = self.lines[i].strip() if l.startswith("*"): break i += 1 tokens = l.replace("|", " ").split() species.append(tokens[0]) frac_coords.append(np.array(list(map(float, tokens[2:5])))) self._structure = Structure(lattice, species, frac_coords) continue # Parse kmesh. if "Grid size" in line: # Grid size = 2 x 2 x 2 Total points = 8 tokens = line.split("=")[1].split("Total")[0].split("x") self.grid_size = np.array(list(map(int, tokens))) continue if not params_done and any(sname in line for sname in self.params_section): #*---------------------------------- MAIN ------------------------------------* #| Number of Wannier Functions : 4 | #| Wavefunction spin channel : up | #*----------------------------------------------------------------------------* # Use params_done to avoid parsing the second section with WANNIERISE key = line.replace("*", "").replace("-", "").strip() i = iln + 1 l = self.lines[i].strip() while not l.startswith("*-"): tokens = [s.strip() for s in l.replace("|", "").split(":")] self.params_section[key][tokens[0]] = tokens[1] i += 1 l = self.lines[i].strip() continue # Extract important metadata from sections and convert from string. self.nwan = int( self.params_section["MAIN"]["Number of Wannier Functions"]) if self.params_section["DISENTANGLE"].get("Using band disentanglement", "F") == "T": self.use_disentangle = True
def read_structure(self): from abipy.core.structure import Structure return Structure.from_file(self.path)
def ebands_input(structure, pseudos, kppa=None, nscf_nband=None, ndivsm=15, ecut=None, pawecutdg=None, scf_nband=None, accuracy="normal", spin_mode="polarized", smearing="fermi_dirac:0.1 eV", charge=0.0, scf_algorithm=None, dos_kppa=None): """ Returns a :class:`AbinitInput` for band structure calculations. Args: structure: :class:`Structure` object. pseudos: List of filenames or list of :class:`Pseudo` objects or :class:`PseudoTable` object. kppa: Defines the sampling used for the SCF run. Defaults to 1000 if not given. nscf_nband: Number of bands included in the NSCF run. Set to scf_nband + 10 if None. ndivsm: Number of divisions used to sample the smallest segment of the k-path. ecut: cutoff energy in Ha (if None, ecut is initialized from the pseudos according to accuracy) pawecutdg: cutoff energy in Ha for PAW double-grid (if None, pawecutdg is initialized from the pseudos according to accuracy) scf_nband: Number of bands for SCF run. If scf_nband is None, nband is automatically initialized from the list of pseudos, the structure and the smearing option. accuracy: Accuracy of the calculation. spin_mode: Spin polarization. smearing: Smearing technique. charge: Electronic charge added to the unit cell. scf_algorithm: Algorithm used for solving of the SCF cycle. dos_kppa: Scalar or List of integers with the number of k-points per atom to be used for the computation of the DOS (None if DOS is not wanted). """ structure = Structure.as_structure(structure) if dos_kppa is not None and not isinstance(dos_kppa, (list, tuple)): dos_kppa = [dos_kppa] multi = MultiDataset(structure, pseudos, ndtset=2 if dos_kppa is None else 2 + len(dos_kppa)) # Set the cutoff energies. multi.set_vars(_find_ecut_pawecutdg(ecut, pawecutdg, multi.pseudos)) # SCF calculation. kppa = _DEFAULTS.get("kppa") if kppa is None else kppa scf_ksampling = aobj.KSampling.automatic_density(structure, kppa, chksymbreak=0) scf_electrons = aobj.Electrons(spin_mode=spin_mode, smearing=smearing, algorithm=scf_algorithm, charge=charge, nband=scf_nband, fband=None) if spin_mode=="polarized": multi[0].set_autospinat() if scf_electrons.nband is None: scf_electrons.nband = _find_scf_nband(structure, multi.pseudos, scf_electrons, multi[0].get('spinat', None)) multi[0].set_vars(scf_ksampling.to_abivars()) multi[0].set_vars(scf_electrons.to_abivars()) multi[0].set_vars(_stopping_criterion("scf", accuracy)) # Band structure calculation. nscf_ksampling = aobj.KSampling.path_from_structure(ndivsm, structure) nscf_nband = scf_electrons.nband + 10 if nscf_nband is None else nscf_nband nscf_electrons = aobj.Electrons(spin_mode=spin_mode, smearing=smearing, algorithm={"iscf": -2}, charge=charge, nband=nscf_nband, fband=None) multi[1].set_vars(nscf_ksampling.to_abivars()) multi[1].set_vars(nscf_electrons.to_abivars()) multi[1].set_vars(_stopping_criterion("nscf", accuracy)) # DOS calculation with different values of kppa. if dos_kppa is not None: for i, kppa in enumerate(dos_kppa): dos_ksampling = aobj.KSampling.automatic_density(structure, kppa, chksymbreak=0) #dos_ksampling = aobj.KSampling.monkhorst(dos_ngkpt, shiftk=dos_shiftk, chksymbreak=0) dos_electrons = aobj.Electrons(spin_mode=spin_mode, smearing=smearing, algorithm={"iscf": -2}, charge=charge, nband=nscf_nband) dt = 2 + i multi[dt].set_vars(dos_ksampling.to_abivars()) multi[dt].set_vars(dos_electrons.to_abivars()) multi[dt].set_vars(_stopping_criterion("nscf", accuracy)) return multi
def structure_from_cif(filename): """ Returnn an Abipy structure from the basename of the cif file in data/cifs. """ return Structure.from_file(cif_file(filename))
def g0w0_with_ppmodel_inputs(structure, pseudos, kppa, nscf_nband, ecuteps, ecutsigx, ecut=None, pawecutdg=None, accuracy="normal", spin_mode="polarized", smearing="fermi_dirac:0.1 eV", ppmodel="godby", charge=0.0, scf_algorithm=None, inclvkb=2, scr_nband=None, sigma_nband=None, gw_qprange=1): """ Returns a :class:`AbinitInput` object that performs G0W0 calculations with the plasmon pole approximation. Args: structure: Pymatgen structure. pseudos: List of filenames or list of :class:`Pseudo` objects or :class:`PseudoTable` object. kppa: Defines the sampling used for the SCF run. nscf_nband: Number of bands included in the NSCF run. ecuteps: Cutoff energy [Ha] for the screening matrix. ecutsigx: Cutoff energy [Ha] for the exchange part of the self-energy. ecut: cutoff energy in Ha (if None, ecut is initialized from the pseudos according to accuracy) pawecutdg: cutoff energy in Ha for PAW double-grid (if None, pawecutdg is initialized from the pseudos according to accuracy) accuracy: Accuracy of the calculation. spin_mode: Spin polarization. smearing: Smearing technique. ppmodel: Plasmonpole technique. charge: Electronic charge added to the unit cell. scf_algorithm: Algorithm used for solving of the SCF cycle. inclvkb: Treatment of the dipole matrix elements (see abinit variable). scr_nband: Number of bands used to compute the screening (default is nscf_nband) sigma_nband: Number of bands used to compute the self-energy (default is nscf_nband) gw_qprange: Option for the automatic selection of k-points and bands for GW corrections. See Abinit docs for more detail. The default value makes the code compute the QP energies for all the point in the IBZ and one band above and one band below the Fermi level. """ structure = Structure.as_structure(structure) multi = MultiDataset(structure, pseudos, ndtset=4) # Set the cutoff energies. multi.set_vars(_find_ecut_pawecutdg(ecut, pawecutdg, multi.pseudos)) scf_ksampling = aobj.KSampling.automatic_density(structure, kppa, chksymbreak=0) scf_electrons = aobj.Electrons(spin_mode=spin_mode, smearing=smearing, algorithm=scf_algorithm, charge=charge, nband=None, fband=None) if scf_electrons.nband is None: scf_electrons.nband = _find_scf_nband(structure, multi.pseudos, scf_electrons) multi[0].set_vars(scf_ksampling.to_abivars()) multi[0].set_vars(scf_electrons.to_abivars()) multi[0].set_vars(_stopping_criterion("scf", accuracy)) nscf_ksampling = aobj.KSampling.automatic_density(structure, kppa, chksymbreak=0) nscf_electrons = aobj.Electrons(spin_mode=spin_mode, smearing=smearing, algorithm={"iscf": -2}, charge=charge, nband=nscf_nband, fband=None) multi[1].set_vars(nscf_ksampling.to_abivars()) multi[1].set_vars(nscf_electrons.to_abivars()) multi[1].set_vars(_stopping_criterion("nscf", accuracy)) # nbdbuf # Screening. if scr_nband is None: scr_nband = nscf_nband screening = aobj.Screening(ecuteps, scr_nband, w_type="RPA", sc_mode="one_shot", hilbert=None, ecutwfn=None, inclvkb=inclvkb) multi[2].set_vars(nscf_ksampling.to_abivars()) multi[2].set_vars(nscf_electrons.to_abivars()) multi[2].set_vars(screening.to_abivars()) multi[2].set_vars(_stopping_criterion("screening", accuracy)) # Dummy #scr_strategy = ScreeningStrategy(scf_strategy, nscf_strategy, screening) # Sigma. if sigma_nband is None: sigma_nband = nscf_nband self_energy = aobj.SelfEnergy("gw", "one_shot", sigma_nband, ecutsigx, screening, gw_qprange=gw_qprange, ppmodel=ppmodel) multi[3].set_vars(nscf_ksampling.to_abivars()) multi[3].set_vars(nscf_electrons.to_abivars()) multi[3].set_vars(self_energy.to_abivars()) multi[3].set_vars(_stopping_criterion("sigma", accuracy)) # Dummy #sigma_strategy = aobj.SelfEnergyStrategy(scf_strategy, nscf_strategy, scr_strategy, self_energy) # TODO: Cannot use istwfk != 1. multi.set_vars(istwfk="*1") return multi