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
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
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)
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
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)