Esempio n. 1
0
    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()
Esempio n. 2
0
    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
Esempio n. 3
0
 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)
Esempio n. 4
0
    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
Esempio n. 5
0
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)
Esempio n. 6
0
    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
Esempio n. 7
0
    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
Esempio n. 8
0
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)
Esempio n. 9
0
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)
Esempio n. 10
0
    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
Esempio n. 11
0
    def __init__(self, structure, pseudo, kppa, connect,
                 ecut=None, pawecutdg=None, ecutsm=0.5,
                 spin_mode="polarized", include_soc=False, toldfe=1.e-9, smearing="fermi_dirac:0.1 eV",
                 chksymbreak=0, workdir=None, manager=None, **kwargs):
        """
        Build a :class:`Work` for the computation of the deltafactor.

        Args:
            structure: :class:`Structure` object
            pseudo: :class:`Pseudo` object.
            kppa: Number of k-points per reciprocal atom.
            connect: True if the SCF run should be initialized from the previous run.
            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(DeltaFactorWork, self).__init__(workdir=workdir, manager=manager)
        self._pseudo = pseudo
        self.include_soc = include_soc

        spin_mode = SpinMode.as_spinmode(spin_mode)
        smearing = Smearing.as_smearing(smearing)

        # Compute the number of bands from the pseudo and the spin-polarization.
        # Add 6 bands to account for smearing.
        #nval = structure.num_valence_electrons(self.pseudo)
        #nband = int(nval / spin_mode.nsppol) + 6

        # Set extra_abivars
        self.ecut, self.pawecutdg = ecut, pawecutdg

        extra_abivars = dict(
            ecut=ecut,
            pawecutdg=pawecutdg,
            ecutsm=ecutsm,
            toldfe=toldfe,
            prtwf=-1 if not connect else 1,
            chkprim=0,
            nstep=200,
            fband=2.0,   # 0.5 is the default value but it's not large enough from some systems.
            #paral_kgb=paral_kgb,
            #nband=nband,
            #mem_test=0,
        )

        extra_abivars.update(**kwargs)
        self._input_structure = structure
        v0 = structure.volume

        # From 94% to 106% of the equilibrium volume.
        self.volumes = v0 * np.arange(94, 108, 2) / 100.

        for vol in self.volumes:
            # Build new structure
            new_lattice = structure.lattice.scale(vol)
            new_structure = Structure(new_lattice, structure.species, structure.frac_coords)

            ksampling = KSampling.automatic_density(new_structure, kppa, chksymbreak=chksymbreak,
                                                    use_time_reversal=spin_mode.nspinor==1)

            scf_input = abilab.AbinitInput(structure=new_structure, pseudos=self.dojo_pseudo)
            scf_input.add_abiobjects(ksampling, smearing, spin_mode)
            scf_input.set_vars(extra_abivars)

            # Magnetic materials with nspinor = 2 requires connection
            # and a double SCF run (nsppol = 2 first then nspinor = 2).
            if connect and spin_mode.nspinor == 2:
                print("Using collinear then noncollinear scf task")
                self.register_collinear_then_noncollinear_scf_task(scf_input)
            else:
                self.register_scf_task(scf_input)

        if connect:
            logger.info("Connecting SCF tasks using previous WFK file")
            middle = len(self.volumes) // 2
            filetype = "WFK"
            for i, task in enumerate(self[:middle]):
                task.add_deps({self[i + 1]: filetype})

            for i, task in enumerate(self[middle+1:]):
                task.add_deps({self[middle + i]: filetype})
ns = 2000  # number of structures to be included in the movie (0 for taking all structures)
skip_freq = 10  # number of structures to be skipped after each structure

ang = 0.529177249


def divide_chunks(l, n):
    # looping till length l
    for i in range(0, len(l), n):
        yield l[i:i + n]


# Reading Files
cellfile = open(pref + '.cel').read().splitlines()
posfile = open(pref + '.pos').read().splitlines()
lats = list(divide_chunks(cellfile, 4))
coords = list(divide_chunks(posfile, len(sp) + 1))

# Loading Structures
structures = []
if (ns == 0):
    ns = len(lats)
for i in range(0, ns, skip_freq):
    tlat = np.loadtxt(lats[i], skiprows=1).transpose() * ang
    tpos = np.loadtxt(coords[i], skiprows=1) * ang
    structures.append(Structure(tlat, sp, tpos, coords_are_cartesian=True))

# Writing output to '[pref]_movie.axsf'
f = open(pref + '_movie.axsf', 'w')
xsf.xsf_write_structure(f, structures)