Ejemplo n.º 1
0
 def write_force_constants(self, fc_format='hdf5'):
     if self.fc is not None:
         if fc_format == 'hdf5':
             p2s_map = self.primitive.get_primitive_to_supercell_map()
             write_force_constants_to_hdf5(self.fc, p2s_map=p2s_map)
         else:
             write_FORCE_CONSTANTS(self.fc)
Ejemplo n.º 2
0
    def get_FC_constant_pressure(self):
        temperatures = self.get_qha_temperatures()
        volumes = self.phonopy_qha.get_volume_temperature()

        for t, v in zip(temperatures[::20], volumes[::20]):
            fc = self.fc_fit.get_total_force_constants(temperature=t, volume=v)
            write_FORCE_CONSTANTS(fc.get_array(), filename='FC_{}'.format(t))
Ejemplo n.º 3
0
def create_FORCE_CONSTANTS(filename, options, log_level):
    fc_and_atom_types = read_force_constant_vasprun_xml(filename)
    if not fc_and_atom_types:
        print
        print "\'%s\' dones not contain necessary information." % filename
        return 1

    force_constants, atom_types = fc_and_atom_types
    if options.is_hdf5:
        try:
            import h5py
        except ImportError:
            print
            print "You need to install python-h5py."
            return 1
    
        write_force_constants_to_hdf5(force_constants)
        if log_level > 0:
            print "force_constants.hdf5 has been created from vasprun.xml."
    else:
        write_FORCE_CONSTANTS(force_constants)
        if log_level > 0:
            print "FORCE_CONSTANTS has been created from vasprun.xml."

    if log_level > 0:
        print "Atom types:", atom_types
    return 0
Ejemplo n.º 4
0
def create_FORCE_CONSTANTS(filename, is_hdf5, log_level):
    fc_and_atom_types = parse_force_constants(filename)

    if not fc_and_atom_types:
        print('')
        print("\'%s\' dones not contain necessary information." % filename)
        return 1

    force_constants, atom_types = fc_and_atom_types
    if is_hdf5:
        try:
            import h5py
        except ImportError:
            print('')
            print("You need to install python-h5py.")
            return 1

        write_force_constants_to_hdf5(force_constants)
        if log_level > 0:
            print("force_constants.hdf5 has been created from vasprun.xml.")
    else:
        write_FORCE_CONSTANTS(force_constants)
        if log_level > 0:
            print("FORCE_CONSTANTS has been created from vasprun.xml.")

    if log_level > 0:
        print("Atom types: %s" % (" ".join(atom_types)))
    return 0
Ejemplo n.º 5
0
    def write_force_constants_pair_sd(
            self,
            filename_write="FORCE_CONSTANTS_PAIR_SD"):

        for (pairtypes, force_constants_pair_sd) in self._force_constants_pair_sd.items():
            filename_write_pair = "{}_{}_{}".format(filename_write, *pairtypes)
            write_FORCE_CONSTANTS(force_constants_pair_sd,
                                  filename_write_pair)
Ejemplo n.º 6
0
    def write_force_constants_pair(
            self,
            filename_write="FORCE_CONSTANTS_PAIR"):

        force_constants_pair = self.get_force_constants_pair()

        for (pairtypes, force_constants_pair) in force_constants_pair.items():
            filename_write_pair = "{}_{}_{}".format(filename_write, *pairtypes)
            write_FORCE_CONSTANTS(force_constants_pair,
                                  filename_write_pair)
Ejemplo n.º 7
0
    def write_phonopy_force_constants(self,
                                      file_name="FORCE_CONSTANTS",
                                      cwd=None):
        """

        Args:
            file_name:
            cwd:

        Returns:

        """
        if cwd is not None:
            file_name = posixpath.join(cwd, file_name)
        write_FORCE_CONSTANTS(force_constants=self.phonopy.force_constants,
                              filename=file_name)
Ejemplo n.º 8
0
 def distribute_fc2(self):
     self._fc2 = np.zeros((self._num_atom, self._num_atom, 3, 3))
     for atom1 in np.arange(self._num_atom):
         for atom2 in np.arange(self._num_atom):
             trans = np.dot(self._coeff2[atom1, atom2], self.irred_trans[self.ifc2_map[atom1, atom2]])
             self._fc2[atom1, atom2] = np.dot(trans, self.irred_fc2).reshape(3,3)
     print "Force constants obtained from MD simulations"
     # show_rotational_invariance(self.force_constants, self.supercell, self.primitive)
     show_drift_force_constants(self.fc2)
     if self._is_trans_inv < 0:
         print "Coerced translational invariance mode, after which"
         set_translational_invariance(self.fc2)
         show_drift_force_constants(self.fc2)
     if self._is_hdf5:
         write_fc2_hdf5(self.fc2)
     else:
         write_FORCE_CONSTANTS(self._fc2, "FORCE_CONSTANTS_MDFC")
Ejemplo n.º 9
0
 def distribute_fc2(self):
     self._fc2 = np.zeros((self._num_atom, self._num_atom, 3, 3))
     for atom1 in np.arange(self._num_atom):
         for atom2 in np.arange(self._num_atom):
             trans = np.dot(self._coeff2[atom1, atom2],
                            self.irred_trans[self.ifc2_map[atom1, atom2]])
             self._fc2[atom1, atom2] = np.dot(trans,
                                              self.irred_fc2).reshape(3, 3)
     print "Force constants obtained from MD simulations"
     # show_rotational_invariance(self.force_constants, self.supercell, self.primitive)
     show_drift_force_constants(self.fc2)
     if self._is_trans_inv < 0:
         print "Coerced translational invariance mode, after which"
         set_translational_invariance(self.fc2)
         show_drift_force_constants(self.fc2)
     if self._is_hdf5:
         write_fc2_hdf5(self.fc2)
     else:
         write_FORCE_CONSTANTS(self._fc2, "FORCE_CONSTANTS_MDFC")
Ejemplo n.º 10
0
def load_phonopy(filename, structure, dim, symprec=0.01, primitive_matrix=None,
                 factor=VaspToTHz, symmetrise=True, born=None, write_fc=False):
    """Load phonopy output and return an ``phonopy.Phonopy`` object.

    Args:
        filename (str): Path to phonopy output. Can be any of ``FORCE_SETS``,
            ``FORCE_CONSTANTS``, or ``force_constants.hdf5``.
        structure (:obj:`~pymatgen.core.structure.Structure`): The unitcell
            structure.
        dim (list): The supercell size, as a :obj:`list` of :obj:`float`.
        symprec (:obj:`float`, optional): The tolerance for determining the
            crystal symmetry.
        primitive_matrix (:obj:`list` or :obj:`str`, optional): The
            transformation matrix from the conventional to primitive cell. Only
            required when the conventional cell was used as the starting
            structure. Should be provided as a 3x3 :obj:`list` of :obj:`float`.
            Alternatively the str 'auto' may be provided.
        factor (:obj:`float`, optional): The conversion factor for phonon
            frequency. Defaults to :obj:`phonopy.units.VaspToTHz`.
        symmetrise (:obj:`bool`, optional): Symmetrise the force constants.
            Defaults to ``True``.
        born (:obj:`str`, optional): Path to file containing Born effective
            charges. Should be in the same format as the file produced by the
            ``phonopy-vasp-born`` script provided by phonopy.
        write_fc (:obj:`bool` or :obj:`str`,  optional): Write the force
            constants to disk. If ``True``, a ``FORCE_CONSTANTS`` file will be
            written. Alternatively, if set to ``"hdf5"``, a
            ``force_constants.hdf5`` file will be written. Defaults to
            ``False`` (force constants not written).
    """
    unitcell = get_phonopy_structure(structure)
    num_atom = unitcell.get_number_of_atoms()
    num_satom = determinant(dim) * num_atom

    phonon = Phonopy(unitcell, dim, primitive_matrix=primitive_matrix,
                     factor=factor, symprec=symprec)

    if 'FORCE_CONSTANTS' == filename or '.hdf5' in filename:
        # if force constants exist, use these to avoid recalculating them
        if '.hdf5' in filename:
            fc = file_IO.read_force_constants_hdf5(filename)

        elif 'FORCE_CONSTANTS' == filename:
            fc = file_IO.parse_FORCE_CONSTANTS(filename=filename)

        if fc.shape[0] != num_satom:
            msg = ("\nNumber of atoms in supercell is not consistent with the "
                   "matrix shape of\nforce constants read from {}.\nPlease"
                   "carefully check --dim.")
            logging.error(msg.format(filename))
            sys.exit()

        phonon.set_force_constants(fc)

    elif 'FORCE_SETS' == filename:
        # load the force sets from file and calculate force constants
        fs = file_IO.parse_FORCE_SETS()

        if fs['natom'] != num_satom:
            msg = ("\nNumber of atoms in supercell is not consistent with the "
                   "the data in FORCE_SETS\nPlease carefully check --dim.")
            logging.error(msg.format(filename))
            sys.exit()

        phonon.set_displacement_dataset(fs)

        logging.info("Calculating force constants...")
        phonon.produce_force_constants()

    if born:
        # load born parameters from a file
        nac_params = file_IO.parse_BORN(phonon._primitive,
                                        symprec=symprec,
                                        filename=born)

        # set the nac unit conversion factor manual,  specific to VASP
        nac_params['factor'] = Hartree * Bohr
        phonon.set_nac_params(nac_params)

    if symmetrise:
        phonon.symmetrize_force_constants()

    if write_fc == 'hdf5':
        file_IO.write_force_constants_to_hdf5(phonon.get_force_constants())
        logging.info("Force constants written to force_constants.hdf5.")

    elif write_fc:
        file_IO.write_FORCE_CONSTANTS(phonon.get_force_constants())
        logging.info("Force constants written to FORCE_CONSTANTS.")

    return phonon
Ejemplo n.º 11
0
def save_force_constants_to_file(force_constants, filename='FORCE_CONSTANTS'):
    # Just a wrapper to phonopy function
    write_FORCE_CONSTANTS(force_constants.get_array(), filename=filename)
Ejemplo n.º 12
0
def calculate_phonon(atoms,
                     calc,
                     ndim=np.eye(3),
                     primitive_matrix=np.eye(3),
                     distance=0.01,
                     factor=VaspToTHz,
                     is_symmetry=True,
                     symprec=1e-5,
                     func=None,
                     **func_args):
    """
    """
    if 'magmoms' in atoms.arrays:
        is_mag = True
    else:
        is_mag = False
    # 1. get displacements and supercells
    atoms.set_calculator(calc)
    # bulk = PhonopyAtoms(atoms=atoms)
    if is_mag:
        bulk = PhonopyAtoms(
            symbols=atoms.get_chemical_symbols(),
            scaled_positions=atoms.get_scaled_positions(),
            cell=atoms.get_cell(),
            magmoms=atoms.arrays['magmoms'],
        )
    else:
        bulk = PhonopyAtoms(symbols=atoms.get_chemical_symbols(),
                            scaled_positions=atoms.get_scaled_positions(),
                            cell=atoms.get_cell())

    phonon = Phonopy(bulk,
                     ndim,
                     primitive_matrix=primitive_matrix,
                     factor=factor,
                     symprec=symprec)
    phonon.generate_displacements(distance=distance)
    disps = phonon.get_displacements()
    for d in disps:
        print("[phonopy] %d %s" % (d[0], d[1:]))
    supercell0 = phonon.get_supercell()
    supercells = phonon.get_supercells_with_displacements()
    write_supercells_with_displacements(supercell0, supercells)
    write_disp_yaml(disps, supercell0)

    # 2. calculated forces.
    set_of_forces = []
    for iscell, scell in enumerate(supercells):
        cell = Atoms(symbols=scell.get_chemical_symbols(),
                     scaled_positions=scell.get_scaled_positions(),
                     cell=scell.get_cell(),
                     pbc=True)
        if is_mag:
            cell.set_initial_magnetic_moments(
                atoms.get_initial_magnetic_moments())
        cell.set_calculator(calc)
        dir_name = "PHON_CELL%s" % iscell
        cur_dir = os.getcwd()
        if not os.path.exists(dir_name):
            os.mkdir(dir_name)
        os.chdir(dir_name)
        forces = cell.get_forces()
        #print "[Phonopy] Forces: %s" % forces
        # Do something other than calculating the forces with func.
        # func: func(atoms, calc, func_args)
        if func is not None:
            func(cell, calc, **func_args)
        os.chdir(cur_dir)
        drift_force = forces.sum(axis=0)
        #print "[Phonopy] Drift force:", "%11.5f" * 3 % tuple(drift_force)
        # Simple translational invariance
        for force in forces:
            force -= drift_force / forces.shape[0]
        set_of_forces.append(forces)

    # Phonopy post-process
    phonon.produce_force_constants(forces=set_of_forces)
    force_constants = phonon.get_force_constants()
    write_FORCE_CONSTANTS(force_constants, filename='FORCE_CONSTANTS')
    print('')
    print("[Phonopy] Phonon frequencies at Gamma:")
    for i, freq in enumerate(phonon.get_frequencies((0, 0, 0))):
        print("[Phonopy] %3d: %10.5f THz" % (i + 1, freq))  # THz
        print("[Phonopy] %3d: %10.5f cm-1" % (i + 1, freq * 33.35))  #cm-1
    return phonon
Ejemplo n.º 13
0
    def phonons(self,
                atoms=None,
                lammps_cmd="",
                enforce_c_size=15.0,
                parameters={}):
        """Make Phonon calculation setup."""
        from phonopy import Phonopy
        from phonopy.file_IO import (
            #    parse_FORCE_CONSTANTS,
            write_FORCE_CONSTANTS, )

        bulk = atoms.phonopy_converter()

        dim = get_supercell_dims(atoms, enforce_c_size=enforce_c_size)
        atoms = atoms.make_supercell([dim[0], dim[1], dim[2]])

        Poscar(atoms).write_file("POSCAR")

        atoms = atoms.make_supercell_matrix([dim[0], dim[1], dim[2]])
        Poscar(atoms).write_file("POSCAR-Super.vasp")

        phonon = Phonopy(bulk,
                         [[dim[0], 0, 0], [0, dim[1], 0], [0, 0, dim[2]]])
        print("[Phonopy] Atomic displacements1:", bulk)
        print("[Phonopy] Atomic displacements2:", phonon, dim[0], dim[1],
              dim[2])
        phonon.generate_displacements(distance=0.03)
        disps = phonon.get_displacements()
        print("[Phonopy] Atomic displacements3:", disps)
        for d in disps:
            print("[Phonopy]", d[0], d[1:])
        supercells = phonon.get_supercells_with_displacements()

        # Force calculations by calculator
        set_of_forces = []
        disp = 0
        from ase import Atoms as AseAtoms

        for scell in supercells:
            ase_atoms = AseAtoms(
                symbols=scell.get_chemical_symbols(),
                scaled_positions=scell.get_scaled_positions(),
                cell=scell.get_cell(),
                pbc=True,
            )
            j_atoms = ase_to_atoms(ase_atoms)
            disp = disp + 1

            parameters["control_file"] = "run0.mod"
            a, b, forces = LammpsJob(
                atoms=j_atoms,
                lammps_cmd=lammps_cmd,
                parameters=parameters,
                jobname="disp-" + str(disp),
            ).runjob()
            print("forces=", forces)
            drift_force = forces.sum(axis=0)
            print("drift forces=", drift_force)
            # Simple translational invariance
            for force in forces:
                force -= drift_force / forces.shape[0]
            set_of_forces.append(forces)
        phonon.produce_force_constants(forces=set_of_forces)

        write_FORCE_CONSTANTS(phonon.get_force_constants(),
                              filename="FORCE_CONSTANTS")
        print()
        print("[Phonopy] Phonon frequencies at Gamma:")
Ejemplo n.º 14
0
def abinit_to_phonopy(anaddbnc,
                      supercell_matrix,
                      symmetrize_tensors=False,
                      output_dir_path=None,
                      prefix_outfiles="",
                      symprec=1e-5,
                      set_masses=False):
    """
    Converts the interatomic force constants(IFC), born effective charges(BEC) and dielectric
    tensor obtained from anaddb to the phonopy format. Optionally writes the
    standard phonopy files to a selected directory: FORCE_CONSTANTS, BORN (if BECs are available)
    POSCAR of the unit cell, POSCAR of the supercell.

    The conversion is performed taking the IFC in the Wigner–Seitz supercell with weights
    as produced by anaddb and reorganizes them in a standard supercell multiple of the
    unit cell. Operations are vectorized using numpy. This may lead to the allocation of
    large arrays in case of very large supercells.

    Performs a check to verify if the two codes identify the same symmetries and it gives a
    warning in case of failure. Mismatching symmetries may lead to incorrect conversions.

    Args:
        anaddbnc: an instance of AnaddbNcFile. Should contain the output of the IFC analysis,
            the BEC and the dielectric tensor.
        supercell_matrix: the supercell matrix used for phonopy. Any choice is acceptable, however
            the best agreement between the abinit and phonopy results is obtained if this is set to
            a diagonal matrix with on the diagonal the ngqpt used to generate the anaddb.nc.
        symmetrize_tensors: if True the tensors will be symmetrized in the Phonopy object and
            in the output files. This will apply to IFC, BEC and dielectric tensor.
        output_dir_path: a path to a directory where the phonopy files will be created
        prefix_outfiles: a string that will be added as a prefix to the name of the written files
        symprec: distance tolerance in Cartesian coordinates to find crystal symmetry in phonopy.
            It might be that the value should be tuned so that it leads to the the same symmetries
            as in the abinit calculation.
        set_masses: if True the atomic masses used by abinit will be added to the PhonopyAtoms
            and will be present in the returned Phonopy object. This should improve compatibility
            among abinit and phonopy results if frequencies needs to be calculated.

    Returns:
        An instance of a Phonopy object that contains the IFC, BEC and dieletric tensor data.
    """

    ifc = anaddbnc.ifc
    nac_params = None
    becs = None
    epsinf = None
    if anaddbnc.becs is not None and anaddbnc.epsinf is not None:
        becs = anaddbnc.becs.values
        epsinf = anaddbnc.epsinf

        # according to the phonopy website 14.399652 is not the coefficient for abinit
        # probably it relies on the other conventions in the output.
        nac_params = {"born": becs, "dielectric": epsinf, "factor": 14.399652}

    s = anaddbnc.structure

    phon_at = get_phonopy_structure(s)
    if set_masses:
        phon_at.masses = [anaddbnc.amu[n] for n in phon_at.numbers]

    # use phonopy to get the proper supercell given by the primitive and the matrix
    # and convert it to pymatgen
    phonon = Phonopy(phon_at,
                     supercell_matrix,
                     primitive_matrix=np.eye(3),
                     nac_params=nac_params,
                     symprec=symprec)
    phon_supercell = phonon.get_supercell()
    supercell = get_pmg_structure(phon_supercell)

    abi_hall_num = s.abi_spacegroup.get_spglib_hall_number()
    spglib_hall_num = phonon.symmetry.dataset["hall_number"]
    if abi_hall_num != spglib_hall_num:
        warnings.warn(
            "The hall number obtained based on the DDB symmetries differs "
            f"from the one calculated with spglib: {abi_hall_num} versus "
            f"{spglib_hall_num}. The conversion may be incorrect. Try changing symprec."
        )

    # convert to phonopy units
    at_cart = ifc.atoms_cart_coord * abu.Bohr_Ang
    ifccc = ifc.ifc_cart_coord * abu.Ha_eV / abu.Bohr_Ang**2
    weights = ifc.ifc_weights
    latt = supercell.lattice

    ifcph = np.zeros((len(s), len(supercell), 3, 3))

    # loop over the atoms in the primitive cell
    # other operations are vectorized using numpy arrays. Some array may require large allocations
    for i, (site, c_list, w_list) in enumerate(zip(s, at_cart, weights)):

        ind_w = np.where(w_list > 0)
        ifccc_loc = ifccc[i, ind_w[0]]

        w_list = w_list[ind_w]
        c_list = c_list[ind_w]

        # align the coordinates of the first atom in the list (the site under consideration)
        # with the site in the primitive cell.
        c_list = c_list - c_list[0] + site.coords

        # convert to fractional coordinates as needed by the Lattice to get the distances
        f_list = latt.get_fractional_coords(c_list)
        sc_fcoords = supercell.frac_coords

        # construct the list of sites of the supercell that are closer to sites in
        # the primitive cell
        dist_and_img = [
            latt.get_distance_and_image(f_list[0], fc) for fc in sc_fcoords
        ]
        # the function gives the translation of the image, but it should be applied to the coordinates.
        # Only the positions are needed
        nearest_sc_fcoords = [
            fc + trasl for (_, trasl), fc in zip(dist_and_img, sc_fcoords)
        ]

        # divide by the corresponding weights. Elements with weights 0 were discarded above
        ifccc_loc = np.transpose(ifccc_loc, (0, 2, 1)) / w_list[:, None, None]

        # create an array with all the possible pairs
        # instantiating this array seems slow but seems still faster than the required loops
        coord_pairs = np.array(
            list(itertools.product(nearest_sc_fcoords, f_list)))

        # find the pairs that match between the coordinates of the modified supercell and the f_list
        ind_match = np.where(
            np.abs(coord_pairs[:, 0] -
                   coord_pairs[:, 1]).sum(axis=1) < 1e-6)[0]
        # set the ifc for phonopy in the final array corresponding to the matching indices.
        n_points_f_list = len(f_list)
        ifcph[i, ind_match // n_points_f_list] = ifccc_loc[ind_match %
                                                           n_points_f_list]

    phonon.set_force_constants(ifcph)
    if symmetrize_tensors:
        phonon.symmetrize_force_constants()

    if output_dir_path:
        makedirs_p(output_dir_path)

        fc_filepath = os.path.join(output_dir_path,
                                   prefix_outfiles + "FORCE_CONSTANTS")
        write_FORCE_CONSTANTS(phonon.get_force_constants(), fc_filepath)

        if becs is not None and epsinf is not None:
            born_filepath = os.path.join(output_dir_path,
                                         prefix_outfiles + "BORN")
            write_BORN(phon_at,
                       borns=becs,
                       epsilon=epsinf,
                       filename=born_filepath,
                       symmetrize_tensors=symmetrize_tensors)

        poscar_filepath = os.path.join(output_dir_path,
                                       prefix_outfiles + "POSCAR")
        poscar = Poscar(s)
        poscar.write_file(poscar_filepath, significant_figures=15)

        supercell_filepath = os.path.join(output_dir_path,
                                          prefix_outfiles + "supercell_POSCAR")
        superce_poscar = Poscar(supercell)
        superce_poscar.write_file(supercell_filepath, significant_figures=15)

    return phonon
Ejemplo n.º 15
0
def calculate_phonon(atoms,
                     calc=None,
                     forces_set_file=None,
                     ndim=np.eye(3),
                     primitive_matrix=np.eye(3),
                     distance=0.01,
                     factor=VaspToTHz,
                     is_plusminus='auto',
                     is_symmetry=True,
                     symprec=1e-5,
                     func=None,
                     prepare_initial_wavecar=False,
                     skip=None,
                     restart=True,
                     parallel=True,
                     sc_mag=None,
                     **func_args):
    """
    """
    if 'magmoms' in atoms.arrays or 'initial_magmoms' in atoms.arrays:
        is_mag = True
    else:
        is_mag = False
    print("is_mag: ", is_mag)
    # 1. get displacements and supercells
    if calc is not None:
        atoms.set_calculator(calc)
    # bulk = PhonopyAtoms(atoms=atoms)
    if is_mag:
        bulk = PhonopyAtoms(
            symbols=atoms.get_chemical_symbols(),
            scaled_positions=atoms.get_scaled_positions(),
            cell=atoms.get_cell(),
            magmoms=atoms.arrays['initial_magmoms'],
        )
    else:
        bulk = PhonopyAtoms(symbols=atoms.get_chemical_symbols(),
                            scaled_positions=atoms.get_scaled_positions(),
                            cell=atoms.get_cell())

    phonon = Phonopy(bulk,
                     ndim,
                     primitive_matrix=primitive_matrix,
                     factor=factor,
                     symprec=symprec)
    phonon.generate_displacements(distance=distance, is_plusminus=is_plusminus)
    disps = phonon.get_displacements()
    for d in disps:
        print(("[phonopy] %d %s" % (d[0], d[1:])))
    supercell0 = phonon.get_supercell()
    supercells = phonon.get_supercells_with_displacements()
    #write_supercells_with_displacements(supercell0, supercells)
    write_disp_yaml(disps, supercell0)

    # 2. calculated forces.
    if forces_set_file is not None:
        symmetry = phonon.get_symmetry()
        set_of_forces = parse_FORCE_SETS(
            is_translational_invariance=False,
            filename=forces_set_file)  # ['first_atoms']
        # set_of_forces=np.array(set_of_forces)
        #set_of_forces=[np.asarray(f) for f in set_of_forces]
        phonon.set_displacement_dataset(set_of_forces)
        phonon.produce_force_constants()
    else:
        # initialize set of forces
        if restart and os.path.exists('forces_set.pickle'):
            try:
                with open("forces_set.pickle", 'rb') as myfile:
                    set_of_forces = pickle.load(myfile)
                iskip = len(set_of_forces) - 1
            except:
                set_of_forces = []
                iskip = -1
        else:
            set_of_forces = []
            iskip = -1

        if prepare_initial_wavecar and skip is None:
            scell = supercell0
            cell = Atoms(symbols=scell.get_chemical_symbols(),
                         scaled_positions=scell.get_scaled_positions(),
                         cell=scell.get_cell(),
                         pbc=True)
            if is_mag:
                cell.set_initial_magnetic_moments(sc_mag)
            write('Supercell.cif', cell)
            mcalc = copy.deepcopy(calc)
            mcalc.set(lwave=True, lcharg=True)
            cell.set_calculator(mcalc)
            dir_name = "SUPERCELL0"
            cur_dir = os.getcwd()
            if not os.path.exists(dir_name):
                os.mkdir(dir_name)
            os.chdir(dir_name)
            mcalc.scf_calculation(cell)
            os.chdir(cur_dir)

        def calc_force(iscell):
            scell = supercells[iscell]
            cell = Atoms(symbols=scell.get_chemical_symbols(),
                         scaled_positions=scell.get_scaled_positions(),
                         cell=scell.get_cell(),
                         pbc=True)
            if is_mag:
                cell.set_initial_magnetic_moments(sc_mag)
            cell.set_calculator(copy.deepcopy(calc))
            dir_name = "PHON_CELL%s" % iscell
            cur_dir = os.getcwd()
            if not os.path.exists(dir_name):
                os.mkdir(dir_name)
            if prepare_initial_wavecar:
                os.system('ln -s %s %s' %
                          (os.path.abspath("SUPERCELL0/WAVECAR"),
                           os.path.join(dir_name, 'WAVECAR')))

            os.chdir(dir_name)
            forces = cell.get_forces()
            print("[Phonopy] Forces: %s" % forces)
            # Do something other than calculating the forces with func.
            # func: func(atoms, calc, func_args)
            if func is not None:
                func(cell, calc, **func_args)
            os.chdir(cur_dir)
            drift_force = forces.sum(axis=0)
            print("[Phonopy] Drift force:", "%11.5f" * 3 % tuple(drift_force))
            # Simple translational invariance
            for force in forces:
                force -= drift_force / forces.shape[0]
            return forces

        if parallel:
            p = Pool()
            set_of_forces = p.map(calc_force,
                                  list(range(iskip, len(supercells))))
        else:
            for iscell, scell in enumerate(supercells):
                if iscell > iskip:
                    fs = calc_force(iscell)
                    set_of_forces.append(fs)
                    with open("forces_set.pickle", 'wb') as myfile:
                        pickle.dump(set_of_forces, myfile)

        phonon.produce_force_constants(forces=np.array(set_of_forces))
    force_constants = phonon.get_force_constants()
    write_FORCE_CONSTANTS(force_constants, filename='FORCE_CONSTANTS')
    #print("[Phonopy] Phonon frequencies at Gamma:")
    # for i, freq in enumerate(phonon.get_frequencies((0, 0, 0))):
    #    print(("[Phonopy] %3d: %10.5f THz" % (i + 1, freq)))  # THz
    #    print(("[Phonopy] %3d: %10.5f cm-1" % (i + 1, freq * 33.35)))  #cm-1
    with open('phonon.pickle', 'wb') as myfile:
        pickle.dump(phonon, myfile)
    phonon.save(settings={'force_constants': True})
    return phonon
Ejemplo n.º 16
0
def BuildForceConstants(lattice_vectors, atom_types, atom_pos, q_pts, freqs, eigs, sc_dim, freq_units = 'thz', atom_mass = None, file_path = r"FORCE_CONSTANTS"):
    """
    Use the Phonopy API to take a set of frequencies and eigenvectors, construct a dynamical matrix, transform to a set of force constants, and write out a Phonopy FORCE_CONSTANTS file.

    Args:
        lattice_vectors -- 3x3 matrix containing the lattice vectors
        atom_types -- list of atomic symbols
        atom_pos -- list of atomic positions ** in fractional coordinates **
        q_pts -- list of q-point coordinates
        freqs -- n_q sets of Frequencies
        eigs -- n_q sets of eigenvectors
        sc_dim -- (equivalent) supercell dimension for preparing force constants
        freq_units -- units of freqs ('thz' or 'inv_cm' -- default: 'thz')
        atom_mass -- (optional) list of atomic masses (default: taken from Phonopy internal database)
        file_path -- path to FORCE_CONSTANTS file to write (default: FORCE_CONSTANTS)
    """

    # Check input.

    _CheckStructure(lattice_vectors, atom_types, atom_pos, atom_mass)

    for param in q_pts, freqs, eigs, sc_dim:
        assert param is not None

    dim_1, dim_2 = np.shape(q_pts)

    assert dim_1 > 0 and dim_2 == 3

    n_at = len(atom_types)

    n_q = dim_1
    n_b = 3 * n_at

    dim_1, dim_2 = np.shape(freqs)

    assert dim_1 == n_q and dim_2 == n_b

    dim_1, dim_2, dim_3, dim_4 = np.shape(eigs)

    assert dim_1 == n_q and dim_2 == n_b and dim_3 == n_at and dim_4 == 3

    dim_1, = np.shape(sc_dim)

    assert dim_1 == 3

    # Obtain a frequency conversion factor to "VASP units".

    freq_conv_factor = None

    if freq_units == 'thz':
        freq_conv_factor = VaspToTHz
    elif freq_units == 'inv_cm':
        freq_conv_factor = VaspToCm

    if freq_conv_factor is None:
        raise Exception("Error: Unknown freq_units '{0}'.".format(freq_units))

    # Create a Phonopy-format structure.

    structure = PhonopyAtoms(
        symbols = atom_types, masses = atom_mass, scaled_positions = atom_pos, cell = lattice_vectors
        )

    # Convert supercell expansion to a supercell matrix.

    dim_1, dim_2, dim_3 = sc_dim

    if dim_1 != dim_2 != dim_2 != 1:
        warnings.warn("The dynamical matrix -> force constants transform has only been tested at the Gamma point; please report issues to the developer.", RuntimeWarning)

    sc_matrix = [[dim_1, 0, 0], [0, dim_2, 0], [0, 0, dim_3]]

    # Use the main Phonopy object to obtain the primitive cell and supercell.

    calculator = Phonopy(structure, sc_matrix)

    primitive = calculator.get_primitive();
    supercell = calculator.get_supercell();

    # Use the DynmatToForceConstants object to convert frequencies/eigenvectors -> dynamical matrices -> force constants.

    dynmat_to_fc = DynmatToForceConstants(primitive, supercell)

    commensurate_points = dynmat_to_fc.get_commensurate_points()

    # If an input code does not use crystal symmetry or outputs data at all q-points in a sampling mesh, data may be provided for more q-points than there are commensurate points.
    # However, for most codes this would be an odd situation -> issue a warning.

    if len(commensurate_points) != n_q:
        warnings.warn("The number of entries in the q_pts list does not equal the number of commensurate points expected for the supplied supercell matrix.", RuntimeWarning)

    # Map commensurate points in Phonopy setup to q-points in input data.

    map_indices = []

    for qx_1, qy_1, qz_1 in commensurate_points:
        map_index = None

        for i, (qx_2, qy_2, qz_2) in enumerate(q_pts):
            if math.fabs(qx_2 - qx_1) < _SymPrec and math.fabs(qy_2 - qy_1) < _SymPrec and math.fabs(qz_2 - qz_1) < _SymPrec:
                map_index = i
                break

        if map_index is None:
            raise Exception("Error: Expected q = ({0: >6.3f}, {1: >6.3f}, {2: >6.3f}) in the q_pts list (this may be a bug; please report to the developer).".format(qx_1, qy_1, qz_1))

        # Sanity check.

        assert map_index not in map_indices

        map_indices.append(map_index)

    # Arrange the frequencies and eigenvectors to the layout required by Phonopy.

    freq_sets, eig_sets = [], []

    for index in map_indices:
        freq_sets.append(
            [freq / freq_conv_factor for freq in freqs[index]]
            )

        eig = eigs[index]

        # Eigenvectors need to be a 3Nx3N matrix in the format:
        # 1_x -> [ m_1, ..., m_3N ]
        # 1_y -> [ m_1, ..., m_3N ]
        # ...
        # N_z -> [ m_1, ..., m_3N ]

        eig_rows = []

        for i in range(0, n_at):
            for j in range(0, 3):
                eig_row = []

                for k in range(0, n_b):
                    eig_row.append(eig[k][i][j])

                eig_rows.append(eig_row)

        eig_sets.append(eig_rows)

    freq_sets = np.array(freq_sets, dtype = np.float64)
    eig_sets = np.array(eig_sets, dtype = np.complex128)

    # Use the DynmatToForceConstants object to build the dynamical matrices, reverse transform to the force constants, and write a Phonopy FORCE_CONSTANTS file.

    dynmat_to_fc.set_dynamical_matrices(freq_sets, eig_sets)

    dynmat_to_fc.run()

    write_FORCE_CONSTANTS(
        dynmat_to_fc.get_force_constants(), filename = file_path
        )
Ejemplo n.º 17
0
import phonopy
from phonopy.file_IO import parse_FORCE_CONSTANTS, write_FORCE_CONSTANTS

phonon = phonopy.load(supercell_matrix=[[2, 0, 0], [0, 2, 0], [0, 0, 2]],
                      primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5],
                                        [0.5, 0.5, 0]],
                      unitcell_filename="POSCAR",
                      force_sets_filename="FORCE_SETS",
                      born_filename="BORN")
write_FORCE_CONSTANTS(phonon.get_force_constants(), filename="FORCE_CONSTANTS")

force_constants = parse_FORCE_CONSTANTS()
phonon.force_constants = force_constants
phonon.symmetrize_force_constants()
write_FORCE_CONSTANTS(phonon.get_force_constants(),
                      filename="FORCE_CONSTANTS_NEW")
Ejemplo n.º 18
0
    def write_force_constants(self, filename_write):

        write_FORCE_CONSTANTS(self._force_constants, filename_write)
Ejemplo n.º 19
0
    def write_force_constants_sd(
            self,
            filename_write="FORCE_CONSTANTS_SD"):

        write_FORCE_CONSTANTS(self._force_constants_sd,
                              filename_write)
Ejemplo n.º 20
0
    atomic_elements=unitcell.get_chemical_symbols(),
    primitive_matrix=primitive_mat)

structure.set_force_constants(
    ForceConstants(force_constants, supercell=np.diag(supercell)))

# generate LAMMPS MD trajectory (requires dynaphopy development)
trajectory = generate_lammps_trajectory(structure,
                                        'in.lammps',
                                        total_time=20,
                                        time_step=0.001,
                                        relaxation_time=5,
                                        silent=False,
                                        supercell=supercell,
                                        memmap=False,
                                        velocity_only=False,
                                        temperature=temperature)

# Calculate renormalized force constants with dynaphopy
calculation = Quasiparticle(trajectory)
with silence_stdout():
    calculation.select_power_spectra_algorithm(2)  # 1: Max. Entrop.  2:FFT
    calculation.plot_renormalized_phonon_dispersion_bands()
    renormalized_force_constants = calculation.get_renormalized_force_constants(
    )

# Save renormalized force constants and unitcell to disk
write_FORCE_CONSTANTS(renormalized_force_constants.get_array(),
                      filename='FORCE_CONSTANTS_{}K'.format(temperature))
phlammps.write_unitcell_POSCAR(filename='POSCAR_unitcell')
Ejemplo n.º 21
0
def do_phonons(strt=None, parameters=None, c_size=15):
    """
    Setting up phonopy job using LAMMPS

    Args:
        strt: Structure object
        parameters: LAMMPS input file parameters
        c_size: cell-size 
    
    """
    # spg_strt = SpacegroupAnalyzer(strt).get_conventional_standard_structure()
    p = get_phonopy_atoms(mat=strt)
    bulk = p

    dim1 = int((float(c_size) / float(max(abs(strt.lattice.matrix[0]))))) + 1
    dim2 = int(float(c_size) / float(max(abs(strt.lattice.matrix[1])))) + 1
    dim3 = int(float(c_size) / float(max(abs(strt.lattice.matrix[2])))) + 1
    Poscar(strt).write_file("POSCAR")
    tmp = strt.copy()
    tmp.make_supercell([dim1, dim2, dim3])
    Poscar(tmp).write_file("POSCAR-Super.vasp")

    # phonon = Phonopy(get_phonopy_atoms(tmp), [[dim1, 0, 0], [0, dim2, 0], [0, 0, dim3]])  # ,
    phonon = Phonopy(bulk, [[dim1, 0, 0], [0, dim2, 0], [0, 0, dim3]])  # ,
    print("[Phonopy] Atomic displacements1:", bulk)
    print("[Phonopy] Atomic displacements2:", phonon, dim1, dim2, dim3)
    phonon.generate_displacements(distance=0.03)
    disps = phonon.get_displacements()
    print("[Phonopy] Atomic displacements3:", disps)
    for d in disps:
        print("[Phonopy]", d[0], d[1:])
    supercells = phonon.get_supercells_with_displacements()

    # Force calculations by calculator
    set_of_forces = []
    disp = 0
    for scell in supercells:
        cell = Atoms(
            symbols=scell.get_chemical_symbols(),
            scaled_positions=scell.get_scaled_positions(),
            cell=scell.get_cell(),
            pbc=True,
        )
        disp = disp + 1

    mat = Poscar(AseAtomsAdaptor().get_structure(cell))
    mat.comment = str("disp-") + str(disp)
    parameters["min"] = "skip"
    parameters["control_file"] = "/users/knc6/in.phonon"
    # a,b,forces=run_job(mat=mat,parameters={'min':'skip','pair_coeff': '/data/knc6/JARVIS-FF-NEW/ALLOY4/Mishin-Ni-Al-2009.eam.alloy', 'control_file': '/users/knc6/in.phonon', 'pair_style': 'eam/alloy', 'atom_style': 'charge'})
    a, b, forces = run_job(mat=mat, parameters=parameters)
    print("forces=", forces)
    drift_force = forces.sum(axis=0)
    print("drift forces=", drift_force)
    print("[Phonopy] Drift force:", "%11.5f" * 3 % tuple(drift_force))
    # Simple translational invariance
    for force in forces:
        force -= drift_force / forces.shape[0]
    set_of_forces.append(forces)
    phonon.produce_force_constants(forces=set_of_forces)

    write_FORCE_CONSTANTS(phonon.get_force_constants(),
                          filename="FORCE_CONSTANTS")
    print()
    print("[Phonopy] Phonon frequencies at Gamma:")
Ejemplo n.º 22
0
def save_force_constants_to_file(force_constants, filename='FORCE_CONSTANTS'):
    #Just a wrapper to phonopy function
    write_FORCE_CONSTANTS(force_constants, filename=filename)
Ejemplo n.º 23
0
 def write_fc_enlarged(self, filename):
     fc = self._fc_enlarged
     write_FORCE_CONSTANTS(fc, filename)
Ejemplo n.º 24
0
    def write_force_constants_sd(
            self,
            filename_write="FORCE_CONSTANTS_SD"):

        fc = self.get_force_constants_sd()
        write_FORCE_CONSTANTS(fc, filename_write)
Ejemplo n.º 25
0
    def write_force_constants_symmetrized(
            self,
            filename_write="FORCE_CONSTANTS_SPG"):

        write_FORCE_CONSTANTS(self._force_constants_symmetrized,
                              filename_write)
Ejemplo n.º 26
0
 def write_force_constants(self, filename_write):
     write_FORCE_CONSTANTS(self._force_constants, filename_write)
Ejemplo n.º 27
0
if settings.get_is_force_constants() == 'read':
    phonon.set_force_constants(fc)

# Impose cutoff radius on force constants
cutoff_radius = settings.get_cutoff_radius()
if cutoff_radius:
    phonon.set_force_constants_zero_with_radius(cutoff_radius)

# Enforce space group symmetry to force constants
if settings.get_fc_spg_symmetry():
    if log_level > 0:
        print('')
        print("Force constants are symmetrized by space group operations.")
        print("This may take some time...")
    phonon.symmetrize_force_constants_by_space_group()
    file_IO.write_FORCE_CONSTANTS(phonon.get_force_constants(),
                                  filename='FORCE_CONSTANTS_SPG')
    if log_level > 0:
        print(
            "Symmetrized force constants are written into "
            "FORCE_CONSTANTS_SPG.")

# Imporse translational invariance and index permulation symmetry to
# force constants
if settings.get_fc_symmetry_iteration() > 0:
    phonon.symmetrize_force_constants(settings.get_fc_symmetry_iteration())

# Write FORCE_CONSTANTS
if settings.get_is_force_constants() == "write":
    if settings.get_is_hdf5():
        file_IO.write_force_constants_to_hdf5(phonon.get_force_constants())
        if log_level > 0:
if True:
    print('Writing partial density of states')
    f = open('partial_density_of_states', 'w')
    for i, j in zip(
            wf.get_result('dos').get_array('frequency'),
            wf.get_result('dos').get_array('partial_dos').T):
        f.write('{} {}\n'.format(i, ' '.join(map(str, j))))
    f.close()

# FORCE CONSTANTS
if True:
    print('Writing FORCE_CONSTANTS')
    from phonopy.file_IO import write_FORCE_CONSTANTS, write_FORCE_SETS
    force_constants = wf.get_result('force_constants').get_array(
        'force_constants')
    write_FORCE_CONSTANTS(force_constants, filename='FORCE_CONSTANTS')

# 2) Load a complete PHONOPY object
phonopy_input = wf.get_parameters()['phonopy_input'].get_dict()
structure = wf.get_result('final_structure')

bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                    positions=[site.position for site in structure.sites],
                    cell=structure.cell)

phonon = Phonopy(bulk,
                 phonopy_input['supercell'],
                 primitive_matrix=phonopy_input['primitive'],
                 distance=phonopy_input['distance'])

phonon.set_force_constants(force_constants)
Ejemplo n.º 29
0
    def write_force_constants_sd(self, filename_write="FORCE_CONSTANTS_SD"):

        fc = self.get_force_constants_sd()
        write_FORCE_CONSTANTS(fc, filename_write)
Ejemplo n.º 30
0
def _calc_bands(atoms, hessian, supercell=(1, 1, 1), outfile=None, grid=None):
    """Calculates the band structure for the given Hessian matrix.

    Args:
        atoms (matdb.atoms.Atoms): atoms object corresponding to the *primitive*
          cell. The specified supercell matrix should  result in a number
          of atoms that matches the dimensionality of the Hessian.
        supercell (tuple): tuple of `int` supercell matrix components; can have either
          3 or 9 components.
        hessian (numpy.ndarray): with shape `(natoms*3, natoms*3)`.
        grid (list): list of `int` specifying the number of divisions in k-space
          along each reciprocal unit vector.
        outfile (str): path to the output `band.yaml` file that should be
          created by this function.

    Returns:
        If `outfile` is None, then this method returns a dictionary that has the
        same format as :func:`from_yaml`.
    """
    #Create a temporary directory in which to work.
    target = mkdtemp()
    bandfile = path.join(target, "band.yaml")

    if grid is None:
        grid = [13, 13, 13]
    if isinstance(supercell, np.ndarray):
        supercell = supercell.flatten()

    #First, roll up the Hessian and write it as a FORCE_CONSTANTS file.
    with chdir(target):
        HR = roll(hessian)
        write_FORCE_CONSTANTS(HR)
        atoms.write("POSCAR", format="vasp")

        #We need to create the band.conf file and write the special
        #paths in k-space at which the phonons should be calculated.
        atom_types = _ordered_unique(atoms.get_chemical_symbols())
        settings = [("FORCE_CONSTANTS", "READ"),
                    ("ATOM_NAME", ' '.join(atom_types)),
                    ("DIM", ' '.join(map(str, supercell))),
                    ("MP", ' '.join(map(str, grid)))]

        labels, bands = parsed_kpath(atoms)
        bandfmt = "{0:.3f} {1:.3f} {2:.3f}"
        sband = []
        for Q in bands:
            sband.append(bandfmt.format(*Q))

        settings.append(("BAND", "  ".join(sband)))
        settings.append(("BAND_LABELS", ' '.join(labels)))

        with open("band.conf", 'w') as f:
            for k, v in settings:
                f.write("{} = {}\n".format(k, v))

    sargs = ["phonopy", "band.conf"]
    xres = execute(sargs, target, venv=True)

    if not path.isfile(bandfile):  #pragma: no cover
        msg.err("could not calculate phonon bands; see errors.")
        msg.std(''.join(xres["output"]))

    result = None
    if outfile is not None:
        #Move the band.yaml file to the new target location.
        from shutil import move
        move(bandfile, outfile)
    else:
        result = from_yaml(bandfile)

    #Remove the temporary directory that we created and return the result.
    rmtree(target)
    return result
Ejemplo n.º 31
0
from phonopy import Phonopy
from phonopy.interface.vasp import read_vasp
from phonopy.file_IO import parse_FORCE_SETS
from phonopy.file_IO import parse_FORCE_CONSTANTS, write_FORCE_CONSTANTS

cell = read_vasp("POSCAR")
phonon = Phonopy(cell, [[2, 0, 0], [0, 2, 0], [0, 0, 2]])
force_sets = parse_FORCE_SETS()
phonon.set_displacement_dataset(force_sets)
phonon.produce_force_constants()
write_FORCE_CONSTANTS(phonon.get_force_constants(), filename="FORCE_CONSTANTS")

force_constants = parse_FORCE_CONSTANTS()
phonon.set_force_constants(force_constants)
phonon.symmetrize_force_constants(iteration=1)
write_FORCE_CONSTANTS(phonon.get_force_constants(), filename="FORCE_CONSTANTS_NEW")
Ejemplo n.º 32
0
 def write(self, filename):
     write_FORCE_CONSTANTS(self._fc_reduced, filename=filename)