def _get_fc3_one_atom(fc3, supercell, disp_dataset, fc2, first_atom_num, site_symmetry, translational_symmetry_type, is_permutation_symmetry, symprec, verbose): displacements_first = [] delta_fc2s = [] for dataset_first_atom in disp_dataset['first_atoms']: if first_atom_num != dataset_first_atom['number']: continue displacements_first.append(dataset_first_atom['displacement']) if 'delta_fc2' in dataset_first_atom: delta_fc2s.append(dataset_first_atom['delta_fc2']) else: direction = np.dot(dataset_first_atom['displacement'], np.linalg.inv(supercell.get_cell())) reduced_site_sym = get_reduced_site_symmetry( site_symmetry, direction, symprec) delta_fc2s.append( get_delta_fc2(dataset_first_atom['second_atoms'], dataset_first_atom['number'], fc2, supercell, reduced_site_sym, translational_symmetry_type, is_permutation_symmetry, symprec)) solve_fc3(fc3, first_atom_num, supercell, site_symmetry, displacements_first, delta_fc2s, symprec, verbose=verbose)
def _get_fc3_done(supercell, disp_dataset, symmetry, array_shape): num_atom = supercell.get_number_of_atoms() fc3_done = np.zeros(array_shape, dtype='byte') symprec = symmetry.get_symmetry_tolerance() lattice = supercell.get_cell().T positions = supercell.get_scaled_positions() rotations = symmetry.get_symmetry_operations()['rotations'] translations = symmetry.get_symmetry_operations()['translations'] atom_mapping = [] for rot, trans in zip(rotations, translations): atom_indices = [ _get_atom_by_symmetry(lattice, positions, rot, trans, i, symprec) for i in range(num_atom) ] atom_mapping.append(atom_indices) for dataset_first_atom in disp_dataset['first_atoms']: first_atom_num = dataset_first_atom['number'] site_symmetry = symmetry.get_site_symmetry(first_atom_num) direction = np.dot(dataset_first_atom['displacement'], np.linalg.inv(supercell.get_cell())) reduced_site_sym = get_reduced_site_symmetry(site_symmetry, direction, symprec) least_second_atom_nums = [] for second_atoms in dataset_first_atom['second_atoms']: if 'included' in second_atoms: if second_atoms['included']: least_second_atom_nums.append(second_atoms['number']) elif 'cutoff_distance' in disp_dataset: min_vec = get_equivalent_smallest_vectors( first_atom_num, second_atoms['number'], supercell, symprec)[0] min_distance = np.linalg.norm(np.dot(lattice, min_vec)) if 'pair_distance' in second_atoms: assert (abs(min_distance - second_atoms['pair_distance']) < 1e-4) if min_distance < disp_dataset['cutoff_distance']: least_second_atom_nums.append(second_atoms['number']) positions_shifted = positions - positions[first_atom_num] least_second_atom_nums = np.unique(least_second_atom_nums) for red_rot in reduced_site_sym: second_atom_nums = [ _get_atom_by_symmetry(lattice, positions_shifted, red_rot, np.zeros(3, dtype='double'), i, symprec) for i in least_second_atom_nums ] second_atom_nums = np.unique(second_atom_nums) for i in range(len(rotations)): rotated_atom1 = atom_mapping[i][first_atom_num] for j in second_atom_nums: fc3_done[rotated_atom1, atom_mapping[i][j]] = 1 return fc3_done
def _get_fc3_done(supercell, disp_dataset, symmetry): num_atom = supercell.get_number_of_atoms() fc3_done = np.zeros((num_atom, num_atom, num_atom), dtype='byte') symprec = symmetry.get_symmetry_tolerance() lattice = supercell.get_cell().T positions = supercell.get_scaled_positions() rotations = symmetry.get_symmetry_operations()['rotations'] translations = symmetry.get_symmetry_operations()['translations'] atom_mapping = [] for rot, trans in zip(rotations, translations): atom_indices = [] for rot_pos in (np.dot(positions, rot.T) + trans): diffs = positions - rot_pos diffs -= np.rint(diffs) diffs = np.dot(diffs, lattice.T) dists = np.sqrt(np.sum(diffs**2, axis=1)) atom_indices.append((np.where(dists < symprec))[0][0]) atom_mapping.append(atom_indices) for dataset_first_atom in disp_dataset['first_atoms']: first_atom_num = dataset_first_atom['number'] site_symmetry = symmetry.get_site_symmetry(first_atom_num) direction = np.dot(dataset_first_atom['displacement'], np.linalg.inv(supercell.get_cell())) reduced_site_sym = get_reduced_site_symmetry(site_symmetry, direction, symprec) least_second_atom_nums = [] for second_atoms in dataset_first_atom['second_atoms']: if second_atoms['included']: least_second_atom_nums.append(second_atoms['number']) positions_shifted = positions - positions[first_atom_num] least_second_atom_nums = np.unique(least_second_atom_nums) second_atom_nums = [] for red_rot in reduced_site_sym: for i in least_second_atom_nums: second_atom_nums.append( _get_atom_by_symmetry(lattice, positions_shifted, red_rot, np.zeros(3, dtype='double'), i, symprec)) second_atom_nums = np.unique(second_atom_nums) for i in range(len(rotations)): rotated_atom1 = atom_mapping[i][first_atom_num] for j in second_atom_nums: fc3_done[rotated_atom1, atom_mapping[i][j]] = 1 return fc3_done
def _get_fc3_least_atoms(supercell, primitive, disp_dataset, fc2, symmetry, is_compact_fc=False, verbose=True): symprec = symmetry.get_symmetry_tolerance() num_satom = supercell.get_number_of_atoms() unique_first_atom_nums = np.unique( [x['number'] for x in disp_dataset['first_atoms']]) if is_compact_fc: num_patom = primitive.get_number_of_atoms() s2p_map = primitive.get_supercell_to_primitive_map() p2p_map = primitive.get_primitive_to_primitive_map() first_atom_nums = [] for i in unique_first_atom_nums: if i != s2p_map[i]: print("Something wrong in disp_fc3.yaml") raise RuntimeError else: first_atom_nums.append(i) fc3 = np.zeros((num_patom, num_satom, num_satom, 3, 3, 3), dtype='double', order='C') else: first_atom_nums = unique_first_atom_nums fc3 = np.zeros((num_satom, num_satom, num_satom, 3, 3, 3), dtype='double', order='C') for first_atom_num in first_atom_nums: site_symmetry = symmetry.get_site_symmetry(first_atom_num) displacements_first = [] delta_fc2s = [] for dataset_first_atom in disp_dataset['first_atoms']: if first_atom_num != dataset_first_atom['number']: continue displacements_first.append(dataset_first_atom['displacement']) if 'delta_fc2' in dataset_first_atom: delta_fc2s.append(dataset_first_atom['delta_fc2']) else: direction = np.dot(dataset_first_atom['displacement'], np.linalg.inv(supercell.get_cell())) reduced_site_sym = get_reduced_site_symmetry( site_symmetry, direction, symprec) delta_fc2s.append( get_delta_fc2(dataset_first_atom['second_atoms'], dataset_first_atom['number'], fc2, supercell, reduced_site_sym, symprec)) fc3_first = solve_fc3(first_atom_num, supercell, site_symmetry, displacements_first, np.array(delta_fc2s, dtype='double', order='C'), symprec, verbose=verbose) if is_compact_fc: fc3[p2p_map[s2p_map[first_atom_num]]] = fc3_first else: fc3[first_atom_num] = fc3_first return fc3
def _get_fc3_done(supercell: PhonopyAtoms, disp_dataset, symmetry: Symmetry, array_shape): num_atom = len(supercell) fc3_done = np.zeros(array_shape, dtype="byte") symprec = symmetry.tolerance lattice = supercell.cell.T positions = supercell.scaled_positions rotations = symmetry.symmetry_operations["rotations"] translations = symmetry.symmetry_operations["translations"] atom_mapping = [] for rot, trans in zip(rotations, translations): atom_indices = [ _get_atom_by_symmetry(lattice, positions, rot, trans, i, symprec) for i in range(num_atom) ] atom_mapping.append(atom_indices) for dataset_first_atom in disp_dataset["first_atoms"]: first_atom_num = dataset_first_atom["number"] site_symmetry = symmetry.get_site_symmetry(first_atom_num) direction = np.dot(dataset_first_atom["displacement"], np.linalg.inv(supercell.cell)) reduced_site_sym = get_reduced_site_symmetry(site_symmetry, direction, symprec) least_second_atom_nums = [] for second_atoms in dataset_first_atom["second_atoms"]: if "included" in second_atoms: if second_atoms["included"]: least_second_atom_nums.append(second_atoms["number"]) elif "cutoff_distance" in disp_dataset: min_vec = get_smallest_vector_of_atom_pair( first_atom_num, second_atoms["number"], supercell, symprec) min_distance = np.linalg.norm(np.dot(lattice, min_vec)) if "pair_distance" in second_atoms: assert abs(min_distance - second_atoms["pair_distance"]) < 1e-4 if min_distance < disp_dataset["cutoff_distance"]: least_second_atom_nums.append(second_atoms["number"]) positions_shifted = positions - positions[first_atom_num] least_second_atom_nums = np.unique(least_second_atom_nums) for red_rot in reduced_site_sym: second_atom_nums = [ _get_atom_by_symmetry( lattice, positions_shifted, red_rot, np.zeros(3, dtype="double"), i, symprec, ) for i in least_second_atom_nums ] second_atom_nums = np.unique(second_atom_nums) for i in range(len(rotations)): rotated_atom1 = atom_mapping[i][first_atom_num] for j in second_atom_nums: fc3_done[rotated_atom1, atom_mapping[i][j]] = 1 return fc3_done
def _get_fc3_least_atoms(supercell, primitive, disp_dataset, fc2, symmetry, is_compact_fc=False, verbose=True): symprec = symmetry.tolerance num_satom = len(supercell) unique_first_atom_nums = np.unique( [x["number"] for x in disp_dataset["first_atoms"]]) if is_compact_fc: num_patom = primitive.get_number_of_atoms() s2p_map = primitive.s2p_map p2p_map = primitive.p2p_map first_atom_nums = [] for i in unique_first_atom_nums: if i != s2p_map[i]: print("Something wrong in disp_fc3.yaml") raise RuntimeError else: first_atom_nums.append(i) fc3 = np.zeros((num_patom, num_satom, num_satom, 3, 3, 3), dtype="double", order="C") else: first_atom_nums = unique_first_atom_nums fc3 = np.zeros((num_satom, num_satom, num_satom, 3, 3, 3), dtype="double", order="C") for first_atom_num in first_atom_nums: site_symmetry = symmetry.get_site_symmetry(first_atom_num) displacements_first = [] delta_fc2s = [] for dataset_first_atom in disp_dataset["first_atoms"]: if first_atom_num != dataset_first_atom["number"]: continue displacements_first.append(dataset_first_atom["displacement"]) if "delta_fc2" in dataset_first_atom: delta_fc2s.append(dataset_first_atom["delta_fc2"]) else: direction = np.dot( dataset_first_atom["displacement"], np.linalg.inv(supercell.cell), ) reduced_site_sym = get_reduced_site_symmetry( site_symmetry, direction, symprec) delta_fc2s.append( _get_delta_fc2( dataset_first_atom["second_atoms"], dataset_first_atom["number"], dataset_first_atom["forces"], fc2, supercell, reduced_site_sym, symprec, )) fc3_first = _solve_fc3( first_atom_num, supercell, site_symmetry, displacements_first, np.array(delta_fc2s, dtype="double", order="C"), symprec, verbose=verbose, ) if is_compact_fc: fc3[p2p_map[s2p_map[first_atom_num]]] = fc3_first else: fc3[first_atom_num] = fc3_first return fc3