def _read_phono3py_fc3(phono3py, symmetrize_fc3r, input_filename, log_level): if input_filename is None: filename = "fc3.hdf5" else: filename = "fc3." + input_filename + ".hdf5" file_exists(filename, log_level) if log_level: print('Reading fc3 from "%s".' % filename) p2s_map = phono3py.primitive.p2s_map try: fc3 = read_fc3_from_hdf5(filename=filename, p2s_map=p2s_map) except RuntimeError: import traceback traceback.print_exc() if log_level: print_error() sys.exit(1) num_atom = phono3py.supercell.get_number_of_atoms() if fc3.shape[1] != num_atom: print("Matrix shape of fc3 doesn't agree with supercell size.") if log_level: print_error() sys.exit(1) if symmetrize_fc3r: set_translational_invariance_fc3(fc3) set_permutation_symmetry_fc3(fc3) phono3py.fc3 = fc3
def produce_fc3( self, forces_fc3, displacement_dataset=None, cutoff_distance=None, # set fc3 zero symmetrize_fc3r=False, is_compact_fc=False, use_alm=False, alm_options=None): if displacement_dataset is None: disp_dataset = self._displacement_dataset else: disp_dataset = displacement_dataset if use_alm: from phono3py.other.alm_wrapper import get_fc3 as get_fc3_alm fc2, fc3 = get_fc3_alm(self._supercell, self._primitive, forces_fc3, disp_dataset, self._symmetry, alm_options=alm_options, is_compact_fc=is_compact_fc, log_level=self._log_level) else: fc2, fc3 = self._get_fc3(forces_fc3, disp_dataset, is_compact_fc=is_compact_fc) if symmetrize_fc3r: if is_compact_fc: set_translational_invariance_compact_fc3( fc3, self._primitive) set_permutation_symmetry_compact_fc3(fc3, self._primitive) if self._fc2 is None: symmetrize_compact_force_constants( fc2, self._primitive) else: set_translational_invariance_fc3(fc3) set_permutation_symmetry_fc3(fc3) if self._fc2 is None: symmetrize_force_constants(fc2) # Set fc2 and fc3 self._fc3 = fc3 # Normally self._fc2 is overwritten in produce_fc2 if self._fc2 is None: self._fc2 = fc2
def set_permutation_symmetry(self): if self._fc2 is not None: set_permutation_symmetry(self._fc2) if self._fc3 is not None: set_permutation_symmetry_fc3(self._fc3)
def produce_fc3( self, forces_fc3=None, displacement_dataset=None, cutoff_distance=None, # set fc3 zero symmetrize_fc3r=False, is_compact_fc=False, fc_calculator=None, fc_calculator_options=None): """Calculate fc3 from displacements and forces Parameters ---------- forces_fc3 : 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). cutoff_distance : float After creating force constants, fc elements where any pair distance in atom triplets larger than cutoff_distance are set zero. symmetrize_fc3r : 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 fc3 shape is False: (supercell, supercell, supecell, 3, 3, 3) True: (primitive, supercell, supecell, 3, 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: disp_dataset = self._displacement_dataset else: disp_dataset = displacement_dataset if forces_fc3 is not None: self.forces = forces_fc3 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 fc_calculator is not None: from phono3py.other.fc_calculator import ( get_fc3, get_displacements_and_forces_fc3) disps, forces = get_displacements_and_forces_fc3(disp_dataset) fc2, fc3 = get_fc3(self._supercell, self._primitive, disps, forces, fc_calculator=fc_calculator, fc_calculator_options=fc_calculator_options, is_compact_fc=is_compact_fc, log_level=self._log_level) else: fc2, fc3 = get_phono3py_fc3(self._supercell, self._primitive, disp_dataset, self._symmetry, is_compact_fc=is_compact_fc, verbose=self._log_level) if symmetrize_fc3r: if is_compact_fc: set_translational_invariance_compact_fc3( fc3, self._primitive) set_permutation_symmetry_compact_fc3(fc3, self._primitive) if self._fc2 is None: symmetrize_compact_force_constants( fc2, self._primitive) else: set_translational_invariance_fc3(fc3) set_permutation_symmetry_fc3(fc3) if self._fc2 is None: symmetrize_force_constants(fc2) # Set fc2 and fc3 self._fc3 = fc3 # Normally self._fc2 is overwritten in produce_fc2 if self._fc2 is None: self._fc2 = fc2
def create_phono3py_force_constants(phono3py, phonon_supercell_matrix, settings, force_to_eVperA=None, distance_to_A=None, compression=None, input_filename=None, output_filename=None, log_level=1): read_fc3 = settings.get_read_fc3() read_fc2 = settings.get_read_fc2() symmetrize_fc3r = (settings.get_is_symmetrize_fc3_r() or settings.get_fc_symmetry()) symmetrize_fc3q = settings.get_is_symmetrize_fc3_q() symmetrize_fc2 = (settings.get_is_symmetrize_fc2() or settings.get_fc_symmetry()) if settings.get_use_alm_fc2(): symmetrize_fc2 = False if settings.get_use_alm_fc3(): symmetrize_fc3r = False alm_options = None if settings.get_use_alm_fc3() or settings.get_use_alm_fc2(): if settings.get_alm_options() is not None: alm_option_types = {'solver': str, 'cutoff_distance': float} alm_options = {} for option_str in settings.get_alm_options().split(","): key, val = [x.strip() for x in option_str.split('=')[:2]] if key.lower() in alm_option_types: option_value = alm_option_types[key.lower()](val) alm_options[key.lower()] = option_value if log_level: show_phono3py_force_constants_settings(read_fc3, read_fc2, symmetrize_fc3r, symmetrize_fc3q, symmetrize_fc2, settings) # fc3 if (settings.get_is_joint_dos() or (settings.get_is_isotope() and not (settings.get_is_bterta() or settings.get_is_lbte())) or settings.get_read_gamma() or settings.get_read_pp() or settings.get_write_phonon() or settings.get_constant_averaged_pp_interaction() is not None): pass else: if read_fc3: # Read fc3.hdf5 if input_filename is None: filename = 'fc3.hdf5' else: filename = 'fc3.' + input_filename + '.hdf5' file_exists(filename, log_level) if log_level: print("Reading fc3 from %s" % filename) p2s_map = phono3py.get_primitive().get_primitive_to_supercell_map() try: fc3 = read_fc3_from_hdf5(filename=filename, p2s_map=p2s_map) except RuntimeError: import traceback traceback.print_exc() if log_level: print_error() sys.exit(1) num_atom = phono3py.get_supercell().get_number_of_atoms() if fc3.shape[1] != num_atom: print("Matrix shape of fc3 doesn't agree with supercell size.") if log_level: print_error() sys.exit(1) if symmetrize_fc3r: set_translational_invariance_fc3(fc3) set_permutation_symmetry_fc3(fc3) phono3py.set_fc3(fc3) else: # fc3 from FORCES_FC3 if not _create_phono3py_fc3(phono3py, force_to_eVperA, distance_to_A, symmetrize_fc3r, symmetrize_fc2, input_filename, output_filename, settings.get_is_compact_fc(), settings.get_use_alm_fc3(), alm_options, compression, log_level): print("fc3 was not created properly.") if log_level: print_error() sys.exit(1) cutoff_distance = settings.get_cutoff_fc3_distance() if cutoff_distance is not None and cutoff_distance > 0: if log_level: print("Cutting-off fc3 by zero (cut-off distance: %f)" % cutoff_distance) phono3py.cutoff_fc3_by_zero(cutoff_distance) if log_level: show_drift_fc3(phono3py.get_fc3(), primitive=phono3py.get_primitive()) # fc2 phonon_primitive = phono3py.get_phonon_primitive() phonon_supercell = phono3py.get_phonon_supercell() p2s_map = phonon_primitive.get_primitive_to_supercell_map() if read_fc2: if input_filename is None: filename = 'fc2.hdf5' else: filename = 'fc2.' + input_filename + '.hdf5' file_exists(filename, log_level) if log_level: print("Reading fc2 from %s" % filename) num_atom = phonon_supercell.get_number_of_atoms() try: phonon_fc2 = read_fc2_from_hdf5(filename=filename, p2s_map=p2s_map) except RuntimeError: import traceback traceback.print_exc() if log_level: print_error() sys.exit(1) if phonon_fc2.shape[1] != num_atom: print("Matrix shape of fc2 doesn't agree with supercell size.") if log_level: print_error() sys.exit(1) if symmetrize_fc2: if phonon_fc2.shape[0] == phonon_fc2.shape[1]: symmetrize_force_constants(phonon_fc2) else: symmetrize_compact_force_constants(phonon_fc2, phonon_primitive) phono3py.set_fc2(phonon_fc2) else: if phonon_supercell_matrix is None: if not _create_phono3py_fc2(phono3py, force_to_eVperA, distance_to_A, symmetrize_fc2, input_filename, settings.get_is_compact_fc(), settings.get_use_alm_fc2(), alm_options, log_level): print("fc2 was not created properly.") if log_level: print_error() sys.exit(1) else: if not _create_phono3py_phonon_fc2(phono3py, force_to_eVperA, distance_to_A, symmetrize_fc2, input_filename, settings.get_is_compact_fc(), settings.get_use_alm_fc2(), alm_options, log_level): print("fc2 was not created properly.") if log_level: print_error() sys.exit(1) if output_filename is None: filename = 'fc2.hdf5' else: filename = 'fc2.' + output_filename + '.hdf5' if log_level: print("Writing fc2 to %s" % filename) write_fc2_to_hdf5(phono3py.get_fc2(), filename=filename, p2s_map=p2s_map, compression=compression) if log_level: show_drift_force_constants(phono3py.get_fc2(), primitive=phonon_primitive, name='fc2')