def get_force_constants3(data_sets, structure, ph_settings): from phono3py.phonon3 import Phono3py from aiida_phonopy.common.utils import phonopy_atoms_from_structure # Generate phonopy phonon object phono3py = Phono3py(phonopy_atoms_from_structure(structure), supercell_matrix=ph_settings.dict.supercell, primitive_matrix=ph_settings.dict.primitive, symprec=ph_settings.dict.symmetry_tolerance, log_level=1) phono3py.produce_fc3(data_sets.get_forces3(), displacement_dataset=data_sets.get_data_sets3(), is_translational_symmetry=True, is_permutation_symmetry=True, is_permutation_symmetry_fc2=True) fc3 = phono3py.get_fc3() fc2 = phono3py.get_fc2() force_constants_2 = ForceConstantsData(data=fc2) force_constants_3 = ForceConstantsData(data=fc3) return { 'force_constants_2order': force_constants_2, 'force_constants_3order': force_constants_3 }
def get_thermal_properties(structure, ph_settings, force_constants_list): from phonopy import Phonopy from aiida_phonopy.common.utils import phonopy_atoms_from_structure free_energy_list = [] entropy_list = [] cv_list = [] temperature = None for fc in force_constants_list: phonon = Phonopy(phonopy_atoms_from_structure(structure), ph_settings.dict.supercell, primitive_matrix=ph_settings.dict.primitive, symprec=ph_settings.dict.symmetry_tolerance) # Normalization factor primitive to unit cell normalization_factor = phonon.unitcell.get_number_of_atoms( ) / phonon.primitive.get_number_of_atoms() phonon.set_force_constants(fc) phonon.set_mesh(ph_settings.dict.mesh, is_eigenvectors=True, is_mesh_symmetry=False) phonon.set_thermal_properties() temperature, free_energy, entropy, cv = phonon.get_thermal_properties() free_energy_list.append(np.array(free_energy) * normalization_factor) entropy_list.append(np.array(entropy) * normalization_factor) cv_list.append(np.array(cv) * normalization_factor) return np.array(free_energy_list), np.array(entropy_list).T, np.array( cv_list).T, temperature
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_phonon(pk, pk_nac): n = load_node(pk) unitcell = phonopy_atoms_from_structure(n.inputs.structure) smat = n.outputs.phonon_setting_info['supercell_matrix'] ph = Phonopy(unitcell, supercell_matrix=smat, primitive_matrix='auto') force_sets = n.outputs.force_sets.get_array('force_sets') dataset = n.outputs.phonon_setting_info['displacement_dataset'] ph.dataset = dataset ph.forces = force_sets ph.nac_params = get_nac_params(pk_nac) return ph
def get_phonopy_yaml_txt(structure, settings, supercell_matrix=None, primitive_matrix=None, calculator=None): unitcell = phonopy_atoms_from_structure(structure) ph = Phonopy(unitcell, supercell_matrix=settings['supercell_matrix'], primitive_matrix='auto', calculator=calculator) phpy_yaml = PhonopyYaml() phpy_yaml.set_phonon_info(ph) return str(phpy_yaml)
def create_supercells_with_displacements_using_phono3py( structure, ph_settings, cutoff): """ Use phono3py to create the supercells with displacements to calculate the force constants by using finite displacements methodology :param structure: StructureData object :param phonopy_input: Dict object containing a dictionary with the data needed for phonopy :param cutoff: FloatData object containing the value of the cutoff for 3rd order FC in Angstroms (if 0 no cutoff is applied) :return: A set of StructureData Objects containing the supercells with displacements """ from phono3py.phonon3 import Phono3py from aiida_phonopy.common.utils import phonopy_atoms_from_structure # Generate phonopy phonon object phono3py = Phono3py(phonopy_atoms_from_structure(structure), supercell_matrix=ph_settings.dict.supercell, primitive_matrix=ph_settings.dict.primitive, symprec=ph_settings.dict.symmetry_tolerance, log_level=1) if float(cutoff) == 0: cutoff = None else: cutoff = float(cutoff) phono3py.generate_displacements(distance=ph_settings.dict.distance, cutoff_pair_distance=cutoff) cells_with_disp = phono3py.get_supercells_with_displacements() # Transform cells to StructureData and set them ready to return data_sets = phono3py.get_displacement_dataset() data_sets_object = ForceSetsData(data_sets3=data_sets) disp_cells = {'data_sets': data_sets_object} for i, phonopy_supercell in enumerate(cells_with_disp): if phonopy_supercell is None: print('structure_{} cutoff skip'.format(i)) continue supercell = StructureData(cell=phonopy_supercell.get_cell()) for symbol, position in zip(phonopy_supercell.get_chemical_symbols(), phonopy_supercell.get_positions()): supercell.append_atom(position=position, symbols=symbol) disp_cells['structure_{}'.format(i)] = supercell return disp_cells
def get_commensurate(structure, ph_settings): from phonopy import Phonopy from phonopy.harmonic.dynmat_to_fc import DynmatToForceConstants from aiida_phonopy.common.utils import phonopy_atoms_from_structure phonon = Phonopy(phonopy_atoms_from_structure(structure), ph_settings.dict.supercell, primitive_matrix=ph_settings.dict.primitive, symprec=ph_settings.dict.symmetry_tolerance) primitive = phonon.get_primitive() supercell = phonon.get_supercell() dynmat2fc = DynmatToForceConstants(primitive, supercell) commensurate = dynmat2fc.get_commensurate_points() return dynmat2fc, commensurate
def get_phonon(structure, force_constants, ph_settings, nac_data=None): from phonopy import Phonopy from aiida_phonopy.common.utils import phonopy_atoms_from_structure phonon = Phonopy(phonopy_atoms_from_structure(structure), ph_settings.dict.supercell, primitive_matrix=ph_settings.dict.primitive, symprec=ph_settings.dict.symmetry_tolerance) if force_constants is not None: phonon.set_force_constants(force_constants.get_data()) if nac_data is not None: primitive = phonon.get_primitive() nac_parameters = nac_data.get_born_parameters_phonopy( primitive_cell=primitive.get_cell()) phonon.set_nac_params(nac_parameters) return phonon
def get_BORN_txt(nac_data, structure, symmetry_tolerance): """Returns a string of BORN file. nac_data : ArrayData Born effective charges and dielectric constants structure : StructureData This is assumed to be the primitive cell in workchain. symmetry_tolerance : float Symmetry tolerance. """ from phonopy.file_IO import get_BORN_lines born_charges = nac_data.get_array('born_charges') epsilon = nac_data.get_array('epsilon') pcell = phonopy_atoms_from_structure(structure) lines = get_BORN_lines(pcell, born_charges, epsilon, symprec=symmetry_tolerance) return "\n".join(lines)
def generate_displacements(self): label = 'force_constants_%d' % self.ctx.iteration fc_array = self.ctx[label].outputs.force_constants fc = fc_array.get_array('force_constants') phonon_setting_info = self.inputs.phonon_settings smat = phonon_setting_info['supercell_matrix'] ph = Phonopy(phonopy_atoms_from_structure(self.inputs.structure), supercell_matrix=smat, primitive_matrix='auto') ph.force_constants = fc if 'random_seed' in self.inputs: random_seed = self.inputs.random_seed.value else: random_seed = None dataset = _generate_random_displacements( ph, self.inputs.number_of_snapshots.value, self.inputs.temperature.value, random_seed=random_seed) self.ctx.dataset = Dict(dict=dataset)
def bunch_phonons(pks, pk_nac, max_items=None, include_ratio=None, linear_decay=True): nodes = [load_node(pk) for pk in pks] displacements, forces, energies = _extract_dataset_from_db( [n.outputs.force_sets for n in nodes], [n.outputs.phonon_setting_info for n in nodes]) d, f, e, idx = _create_dataset(displacements, forces, energies, max_items, include_ratio, linear_decay=linear_decay) unitcell = phonopy_atoms_from_structure(nodes[0].inputs.structure) smat = nodes[0].outputs.phonon_setting_info['supercell_matrix'] ph = Phonopy(unitcell, supercell_matrix=smat, primitive_matrix='auto') ph.dataset = {'displacements': d, 'forces': f} ph.nac_params = get_nac_params(pk_nac) return ph
def get_random_displacements(structure, number_of_snapshots, temperature, phonon_setting_info, dataset_for_fc, random_seed=None): """Generate supercells with random displacemens The random displacements are generated from phonons and harmonic oscillator distribution function of canonical ensemble. The input phonons are calculated from force constants calculated from forces and displacemens of the supercell snapshots in previous phonon calculation steps. Returns ------- dataset : Dict Displacement datasets to run force calculations. """ # Calculate force constants by fitting using ALM smat = phonon_setting_info['supercell_matrix'] ph = Phonopy(phonopy_atoms_from_structure(structure), supercell_matrix=smat, primitive_matrix='auto') d = dataset_for_fc.get_array('displacements') f = dataset_for_fc.get_array('forces') ph.dataset = {'displacements': d, 'forces': f} ph.produce_force_constants(fc_calculator='alm') if random_seed is not None: _random_seed = random_seed.value else: _random_seed = None dataset = _generate_random_displacements(ph, number_of_snapshots.value, temperature.value, random_seed=_random_seed) return Dict(dict=dataset)
def dump_phonopy(pk): n = load_node(pk) unitcell = phonopy_atoms_from_structure(n.inputs.structure) smat = n.outputs.phonon_setting_info['supercell_matrix'] ph = Phonopy(unitcell, smat, primitive_matrix='auto') force_sets = n.outputs.force_sets.get_array('force_sets') dataset = n.outputs.phonon_setting_info['displacement_dataset'] ph.dataset = dataset ph.forces = force_sets if 'nac_params' in n.outputs: borns = n.outputs.nac_params.get_array('born_charges') epsilon = n.outputs.nac_params.get_array('epsilon') nac_params = { 'born': borns, 'factor': 14.399652, 'dielectric': epsilon } ph.nac_params = nac_params # phonopy-params.yaml is written out. ph.save() print("phonopy_params.yaml was made for PK=%d" % pk)
def get_grid_points(structure, parameters): from phono3py.phonon3 import Phono3py from phono3py.cui.triplets_info import get_coarse_ir_grid_points from aiida_phonopy.common.utils import phonopy_atoms_from_structure # Generate phonopy phonon object phono3py = Phono3py(phonopy_atoms_from_structure(structure), supercell_matrix=parameters.dict.supercell, primitive_matrix=parameters.dict.primitive, symprec=parameters.dict.symmetry_tolerance, log_level=1) primitive = phono3py.get_primitive() (ir_grid_points, grid_weights, bz_grid_address, grid_mapping_table) = get_coarse_ir_grid_points(primitive, parameters.dict.mesh, None, None, is_kappa_star=True, symprec=1e-5) return ir_grid_points
def get_disp_fc3_txt(structure, parameters_data, force_sets): from phono3py.file_IO import write_cell_yaml dataset = force_sets.get_datasets3() supercell = get_supercell(phonopy_atoms_from_structure(structure), parameters_data.dict.supercell, symprec=parameters_data.dict.symmetry_tolerance) w = StringIO.StringIO() w.write("natom: %d\n" % dataset['natom']) num_first = len(dataset['first_atoms']) w.write("num_first_displacements: %d\n" % num_first) if 'cutoff_distance' in dataset: w.write("cutoff_distance: %f\n" % dataset['cutoff_distance']) num_second = 0 num_disp_files = 0 for d1 in dataset['first_atoms']: num_disp_files += 1 num_second += len(d1['second_atoms']) for d2 in d1['second_atoms']: if 'included' in d2: if d2['included']: num_disp_files += 1 else: num_disp_files += 1 w.write("num_second_displacements: %d\n" % num_second) w.write("num_displacements_created: %d\n" % num_disp_files) w.write("first_atoms:\n") count1 = 1 count2 = num_first + 1 for disp1 in dataset['first_atoms']: disp_cart1 = disp1['displacement'] w.write("- number: %5d\n" % (disp1['number'] + 1)) w.write(" displacement:\n") w.write(" [%20.16f,%20.16f,%20.16f ] # %05d\n" % (disp_cart1[0], disp_cart1[1], disp_cart1[2], count1)) w.write(" second_atoms:\n") count1 += 1 included = None atom2 = -1 for disp2 in disp1['second_atoms']: if atom2 != disp2['number']: atom2 = disp2['number'] if 'included' in disp2: included = disp2['included'] pair_distance = disp2['pair_distance'] w.write(" - number: %5d\n" % (atom2 + 1)) w.write(" distance: %f\n" % pair_distance) if included is not None: if included: w.write(" included: %s\n" % "true") else: w.write(" included: %s\n" % "false") w.write(" displacements:\n") disp_cart2 = disp2['displacement'] w.write(" - [%20.16f,%20.16f,%20.16f ] # %05d\n" % (disp_cart2[0], disp_cart2[1], disp_cart2[2], count2)) count2 += 1 write_cell_yaml(w, supercell) w.seek(0) lines = w.read() w.close() return lines