Beispiel #1
0
def get_random_displacements(structure, number_of_snapshots, temperature,
                             **data):
    displacements = []
    forces = []
    energies = []

    for i in range(len(data) // 2):
        forces.append(data['forces_%d' % (i + 1)].get_array('force_sets'))
        if 'energies' in data['forces_%d' % (i + 1)].get_arraynames():
            energies.append(data['forces_%d' % (i + 1)].get_array('energies'))
        phonon_setting_info = data['ph_info_%d' % (i + 1)]
        dataset = phonon_setting_info['displacement_dataset']
        disps, _ = get_displacements_and_forces(dataset)
        displacements.append(disps)
    d = np.concatenate(displacements, axis=0)
    f = np.concatenate(forces, axis=0)

    idx = None
    if len(energies) == len(forces) and 'include_ratio' in data:
        all_energies = np.concatenate(energies)
        if len(all_energies) == len(f):
            ratio = data['include_ratio'].value
            if 0 < ratio and ratio < 1:
                num_include = int(np.ceil(ratio * len(all_energies)))
                if num_include > len(all_energies):
                    num_include = len(all_energies)
                idx = np.argsort(all_energies)[:num_include]
                d = d[idx]
                f = f[idx]

    phonon_setting_info = data['ph_info_1']
    smat = phonon_setting_info['supercell_matrix']
    ph = phonopy.load(unitcell=phonopy_atoms_from_structure(structure),
                      supercell_matrix=smat,
                      primitive_matrix='auto')
    ph.dataset = {'displacements': d, 'forces': f}
    ph.produce_force_constants(fc_calculator='alm')

    _modify_force_constants(ph)

    if 'random_seed' in data:
        _random_seed = data['random_seed'].value
    else:
        _random_seed = None

    ph.generate_displacements(number_of_snapshots=number_of_snapshots.value,
                              random_seed=_random_seed,
                              temperature=temperature.value)

    ret_dict = {'displacement_dataset': Dict(dict=ph.dataset)}

    if idx is not None:
        array = DataFactory('array')()
        array.set_array('supercell_energies', all_energies)
        array.set_array('included_supercell_indices', idx)
        ret_dict['supercell_energies'] = array

    return ret_dict
Beispiel #2
0
def get_force_sets_wien2k(num_displacements,
                          force_filenames,
                          disp_filename,
                          supercell,
                          disp_dataset,
                          wien2k_P1_mode=False,
                          symmetry_tolerance=None,
                          verbose=False):
    from phonopy.interface.wien2k import parse_set_of_forces
    disps, _ = get_displacements_and_forces(disp_dataset)
    force_sets = parse_set_of_forces(disps,
                                     force_filenames,
                                     supercell,
                                     wien2k_P1_mode=wien2k_P1_mode,
                                     symmetry_tolerance=symmetry_tolerance,
                                     verbose=verbose)
    return force_sets
Beispiel #3
0
def _get_dataset(f,
                 natom=None,
                 is_translational_invariance=False,
                 to_type2=False):
    first_line_ary = _get_line_ignore_blank(f).split()
    f.seek(0)
    if len(first_line_ary) == 1:
        if natom is None or int(first_line_ary[0]) == natom:
            dataset = _get_dataset_type1(f, is_translational_invariance)
        else:
            msg = "Number of forces is not consistent with supercell setting."
            raise RuntimeError(msg)

        if to_type2:
            from phonopy.harmonic.displacement import (
                get_displacements_and_forces)
            disps, forces = get_displacements_and_forces(dataset)
            return {'displacements': disps, 'forces': forces}
        else:
            return dataset

    elif len(first_line_ary) == 6:
        return _get_dataset_type2(f, natom)
Beispiel #4
0
def create_FORCE_SETS(interface_mode,
                      force_filenames,
                      symmetry_tolerance=None,
                      is_wien2k_p1=False,
                      force_sets_zero_mode=False,
                      disp_filename='disp.yaml',
                      force_sets_filename='FORCE_SETS',
                      log_level=0):
    if log_level > 0:
        if interface_mode:
            print("Calculator interface: %s" % interface_mode)
        print("Displacements were read from \"%s\"." % disp_filename)
        if disp_filename == 'disp.yaml':
            print('')
            print("NOTE:")
            print("  From phonopy v2.0, displacements are written into "
                  "\"phonopy_disp.yaml\".")
            print("  \"disp.yaml\" is still supported for reading, but is "
                  "deprecated.")
            print('')
        if force_sets_zero_mode:
            print("Forces in %s are subtracted from forces in all "
                  "other files." % force_filenames[0])

    if disp_filename == 'disp.yaml':
        disp_dataset, supercell = parse_disp_yaml(filename=disp_filename,
                                                  return_cell=True)
    else:
        phpy = PhonopyYaml()
        phpy.read(disp_filename)
        supercell = phpy.supercell
        disp_dataset = phpy.dataset

    if 'natom' in disp_dataset:  # type-1 dataset
        num_atoms = disp_dataset['natom']
        num_displacements = len(disp_dataset['first_atoms'])
        dataset_type = 1
    elif 'displacements' in disp_dataset:  # type-2 dataset
        num_atoms = disp_dataset['displacements'].shape[1]
        num_displacements = disp_dataset['displacements'].shape[0]
        dataset_type = 2
    else:
        raise RuntimeError("Number of atoms could not be retrieved from %s" %
                           disp_filename)
    if force_sets_zero_mode:
        num_displacements += 1

    if interface_mode in (None, 'vasp', 'abinit', 'elk', 'qe', 'siesta',
                          'cp2k', 'crystal', 'dftbp', 'turbomole'):
        force_sets = get_force_sets(interface_mode,
                                    num_atoms,
                                    num_displacements,
                                    force_filenames,
                                    disp_filename=disp_filename,
                                    check_number_of_files=True,
                                    verbose=(log_level > 0))
    elif interface_mode == 'wien2k':
        from phonopy.interface.wien2k import parse_set_of_forces
        if not _check_number_of_files(num_displacements, force_filenames,
                                      disp_filename):
            force_sets = []
        else:
            disps, _ = get_displacements_and_forces(disp_dataset)
            force_sets = parse_set_of_forces(
                disps,
                force_filenames,
                supercell,
                is_distribute=(not is_wien2k_p1),
                symmetry_tolerance=symmetry_tolerance,
                verbose=(log_level > 0))
    else:
        force_sets = []

    if force_sets:
        if force_sets_zero_mode:
            force_sets = _subtract_residual_forces(force_sets)
        if dataset_type == 1:
            for forces, disp in zip(force_sets, disp_dataset['first_atoms']):
                disp['forces'] = forces
        elif dataset_type == 2:
            disp_dataset['forces'] = np.array(force_sets,
                                              dtype='double',
                                              order='C')
        else:
            raise RuntimeError("FORCE_SETS could not be created.")

        write_FORCE_SETS(disp_dataset, filename=force_sets_filename)

    if log_level > 0:
        if force_sets:
            print("%s has been created." % force_sets_filename)
        else:
            print("%s could not be created." % force_sets_filename)

    return 0
Beispiel #5
0
    def produce_fc2(self,
                    forces_fc2=None,
                    displacement_dataset=None,
                    symmetrize_fc2=False,
                    is_compact_fc=False,
                    fc_calculator=None,
                    fc_calculator_options=None):
        """Calculate fc2 from displacements and forces

        Parameters
        ----------
        forces_fc2 :
            Dummy argument
        displacement_dataset : dict
            Displacements in supercells. There are two types of formats.
            Type 1. Two atomic displacement in each supercell:
                {'natom': number of atoms in supercell,
                 'first_atoms': [
                   {'number': atom index of first displaced atom,
                    'displacement': displacement in Cartesian coordinates,
                    'forces': forces on atoms in supercell,
                    'second_atoms': [
                      {'number': atom index of second displaced atom,
                       'displacement': displacement in Cartesian coordinates},
                       'forces': forces on atoms in supercell,
                      ... ] }, ... ] }
            Type 2. All atomic displacements in each supercell:
                {'displacements': ndarray, dtype='double', order='C',
                                  shape=(supercells, atoms in supercell, 3)
                 'forces': ndarray, dtype='double',, order='C',
                                  shape=(supercells, atoms in supercell, 3)}
            In type 2, displacements and forces can be given by numpy array
            with different shape but that can be reshaped to
            (supercells, natom, 3).
        symmetrize_fc2 : bool
            Only for type 1 displacement_dataset, translational and
            permutation symmetries are applied after creating fc3. This
            symmetrization is not very sophisticated and can break space
            group symmetry, but often useful. If better symmetrization is
            expected, it is recommended to use external force constants
            calculator such as ALM. Default is False.
        is_compact_fc : bool
            fc2 shape is
                False: (supercell, supecell, 3, 3)
                True: (primitive, supecell, 3, 3)
            where 'supercell' and 'primitive' indicate number of atoms in these
            cells. Default is False.
        fc_calculator : str or None
            Force constants calculator given by str.
        fc_calculator_options : dict
            Options for external force constants calculator.

        """

        if displacement_dataset is None:
            if self._phonon_displacement_dataset is None:
                disp_dataset = self._displacement_dataset
            else:
                disp_dataset = self._phonon_displacement_dataset
        else:
            disp_dataset = displacement_dataset

        if forces_fc2 is not None:
            self.phonon_forces = forces_fc2
            msg = ("Forces have to be stored in disp_dataset as written in "
                   "this method's docstring for the type1 dataset.")
            warnings.warn(msg, DeprecationWarning)

        if is_compact_fc:
            p2s_map = self._phonon_primitive.p2s_map
        else:
            p2s_map = None

        if fc_calculator is not None:
            disps, forces = get_displacements_and_forces(disp_dataset)
            self._fc2 = get_fc2(self._phonon_supercell,
                                self._phonon_primitive,
                                disps,
                                forces,
                                fc_calculator=fc_calculator,
                                fc_calculator_options=fc_calculator_options,
                                atom_list=p2s_map,
                                log_level=self._log_level)
        else:
            self._fc2 = get_phonopy_fc2(self._phonon_supercell,
                                        self._phonon_supercell_symmetry,
                                        disp_dataset,
                                        atom_list=p2s_map)
            if symmetrize_fc2:
                if is_compact_fc:
                    symmetrize_compact_force_constants(self._fc2,
                                                       self._phonon_primitive)
                else:
                    symmetrize_force_constants(self._fc2)