static Cell * expand_positions(SPGCONST Cell * conv_prim, SPGCONST Symmetry * conv_sym) { int i, j, k, num_pure_trans; int num_atom; Cell * bravais; num_pure_trans = get_number_of_pure_translation(conv_sym); bravais = cel_alloc_cell(conv_prim->size * num_pure_trans); num_atom = 0; for (i = 0; i < conv_sym->size; i++) { /* Referred atoms in Bravais lattice */ if (mat_check_identity_matrix_i3(identity, conv_sym->rot[i])) { for (j = 0; j < conv_prim->size; j++) { bravais->types[num_atom] = conv_prim->types[j]; mat_copy_vector_d3(bravais->position[ num_atom ], conv_prim->position[j]); for (k = 0; k < 3; k++) { bravais->position[num_atom][k] += conv_sym->trans[i][k]; bravais->position[num_atom][k] = mat_Dmod1(bravais->position[num_atom][k]); } num_atom++; } } } mat_copy_matrix_d3(bravais->lattice, conv_prim->lattice); return bravais; }
static int get_rotation_axis(SPGCONST int proper_rot[3][3]) { int i, axis = -1; int vec[3]; /* No specific axis for I and -I */ if (mat_check_identity_matrix_i3(proper_rot, identity)) { goto end; } /* Look for eigenvector = rotation axis */ for (i = 0; i < NUM_ROT_AXES; i++) { mat_multiply_matrix_vector_i3(vec, proper_rot, rot_axes[i]); if (vec[0] == rot_axes[i][0] && vec[1] == rot_axes[i][1] && vec[2] == rot_axes[i][2]) { axis = i; break; } } end: #ifdef SPGDEBUG if (axis == -1) { printf("rotation axis cound not found.\n"); } #endif return axis; }
static MatINT *get_point_group_reciprocal(const MatINT * rotations, const int is_time_reversal) { int i, j, num_rot; MatINT *rot_reciprocal, *rot_return; int *unique_rot; SPGCONST int inversion[3][3] = { {-1, 0, 0 }, { 0,-1, 0 }, { 0, 0,-1 } }; if (is_time_reversal) { rot_reciprocal = mat_alloc_MatINT(rotations->size * 2); } else { rot_reciprocal = mat_alloc_MatINT(rotations->size); } unique_rot = (int*)malloc(sizeof(int) * rot_reciprocal->size); for (i = 0; i < rot_reciprocal->size; i++) { unique_rot[i] = -1; } for (i = 0; i < rotations->size; i++) { mat_transpose_matrix_i3(rot_reciprocal->mat[i], rotations->mat[i]); if (is_time_reversal) { mat_multiply_matrix_i3(rot_reciprocal->mat[rotations->size+i], inversion, rot_reciprocal->mat[i]); } } num_rot = 0; for (i = 0; i < rot_reciprocal->size; i++) { for (j = 0; j < num_rot; j++) { if (mat_check_identity_matrix_i3(rot_reciprocal->mat[unique_rot[j]], rot_reciprocal->mat[i])) { goto escape; } } unique_rot[num_rot] = i; num_rot++; escape: ; } rot_return = mat_alloc_MatINT(num_rot); for (i = 0; i < num_rot; i++) { mat_copy_matrix_i3(rot_return->mat[i], rot_reciprocal->mat[unique_rot[i]]); } free(unique_rot); mat_free_MatINT(rot_reciprocal); return rot_return; }
static int get_number_of_pure_translation(SPGCONST Symmetry * conv_sym) { int i, num_pure_trans = 0; for (i = 0; i < conv_sym->size; i++) { if (mat_check_identity_matrix_i3(identity, conv_sym->rot[i])) { num_pure_trans++; } } return num_pure_trans; }
static Symmetry * get_primitive_db_symmetry(SPGCONST double t_mat[3][3], const Symmetry *conv_sym, const double symprec) { int i, j, num_op; double inv_mat[3][3], tmp_mat[3][3]; MatINT *r_prim; VecDBL *t_prim; Symmetry *prim_sym; r_prim = mat_alloc_MatINT(conv_sym->size); t_prim = mat_alloc_VecDBL(conv_sym->size); mat_inverse_matrix_d3(inv_mat, t_mat, symprec); num_op = 0; for (i = 0; i < conv_sym->size; i++) { for (j = 0; j < i; j++) { if (mat_check_identity_matrix_i3(conv_sym->rot[i], conv_sym->rot[j])) { goto pass; } } /* R' = T*R*T^-1 */ mat_multiply_matrix_di3(tmp_mat, t_mat, conv_sym->rot[i]); mat_multiply_matrix_d3(tmp_mat, tmp_mat, inv_mat); mat_cast_matrix_3d_to_3i(r_prim->mat[ num_op ], tmp_mat); /* t' = T*t */ mat_multiply_matrix_vector_d3(t_prim->vec[ num_op ], t_mat, conv_sym->trans[ i ]); num_op++; pass: ; } prim_sym = sym_alloc_symmetry(num_op); for (i = 0; i < num_op; i++) { mat_copy_matrix_i3(prim_sym->rot[i], r_prim->mat[i]); for (j = 0; j < 3; j++) { prim_sym->trans[i][j] = t_prim->vec[i][j] - mat_Nint(t_prim->vec[i][j]); } } mat_free_MatINT(r_prim); mat_free_VecDBL(t_prim); return prim_sym; }
/* num_q is the number of the qpoints. */ static PointSymmetry get_point_group_reciprocal(const MatINT * rotations, const int is_time_reversal) { int i, j, num_pt = 0; MatINT *rot_reciprocal; PointSymmetry point_symmetry; SPGCONST int inversion[3][3] = { {-1, 0, 0 }, { 0,-1, 0 }, { 0, 0,-1 } }; if (is_time_reversal) { rot_reciprocal = mat_alloc_MatINT(rotations->size * 2); } else { rot_reciprocal = mat_alloc_MatINT(rotations->size); } for (i = 0; i < rotations->size; i++) { mat_transpose_matrix_i3(rot_reciprocal->mat[i], rotations->mat[i]); if (is_time_reversal) { mat_multiply_matrix_i3(rot_reciprocal->mat[rotations->size+i], inversion, rot_reciprocal->mat[i]); } } for (i = 0; i < rot_reciprocal->size; i++) { for (j = 0; j < num_pt; j++) { if (mat_check_identity_matrix_i3(point_symmetry.rot[j], rot_reciprocal->mat[i])) { goto escape; } } mat_copy_matrix_i3(point_symmetry.rot[num_pt], rot_reciprocal->mat[i]); num_pt++; escape: ; } point_symmetry.size = num_pt; mat_free_MatINT(rot_reciprocal); return point_symmetry; }
static Symmetry * reduce_operation(SPGCONST Cell * cell, SPGCONST Symmetry * symmetry, const double symprec) { int i, j, num_sym; Symmetry * sym_reduced; PointSymmetry point_symmetry; MatINT *rot; VecDBL *trans; debug_print("reduce_operation:\n"); point_symmetry = get_lattice_symmetry(cell, symprec); rot = mat_alloc_MatINT(symmetry->size); trans = mat_alloc_VecDBL(symmetry->size); num_sym = 0; for (i = 0; i < point_symmetry.size; i++) { for (j = 0; j < symmetry->size; j++) { if (mat_check_identity_matrix_i3(point_symmetry.rot[i], symmetry->rot[j])) { if (is_overlap_all_atoms(symmetry->trans[j], symmetry->rot[j], cell, symprec, 0)) { mat_copy_matrix_i3(rot->mat[num_sym], symmetry->rot[j]); mat_copy_vector_d3(trans->vec[num_sym], symmetry->trans[j]); num_sym++; } } } } sym_reduced = sym_alloc_symmetry(num_sym); for (i = 0; i < num_sym; i++) { mat_copy_matrix_i3(sym_reduced->rot[i], rot->mat[i]); mat_copy_vector_d3(sym_reduced->trans[i], trans->vec[i]); } mat_free_MatINT(rot); mat_free_VecDBL(trans); debug_print(" num_sym %d -> %d\n", symmetry->size, num_sym); return sym_reduced; }
/* Return NULL if failed */ static int * get_mapping_table(SPGCONST Symmetry *symmetry, SPGCONST Cell * cell, const double symprec) { int i, j, k, is_found; double pos[3]; int *mapping_table; SPGCONST int I[3][3] = {{ 1, 0, 0}, { 0, 1, 0}, { 0, 0, 1}}; mapping_table = NULL; if ((mapping_table = (int*) malloc(sizeof(int) * cell->size)) == NULL) { warning_print("spglib: Memory could not be allocated."); return NULL; } for (i = 0; i < cell->size; i++) { is_found = 0; for (j = 0; j < symmetry->size; j++) { if (mat_check_identity_matrix_i3(symmetry->rot[j], I)) { for (k = 0; k < 3; k++) { pos[k] = cell->position[i][k] + symmetry->trans[j][k]; } for (k = 0; k < cell->size; k++) { if (cel_is_overlap(pos, cell->position[k], cell->lattice, symprec)) { if (k < i) { mapping_table[i] = mapping_table[k]; is_found = 1; break; } } } } if (is_found) { break; } } if (!is_found) { mapping_table[i] = i; } } return mapping_table; }
static PointSymmetry get_pointsymmetry(SPGCONST int rotations[][3][3], const int num_rotations) { int i, j; PointSymmetry pointsym; pointsym.size = 0; for (i = 0; i < num_rotations; i++) { for (j = 0; j < pointsym.size; j++) { if (mat_check_identity_matrix_i3(rotations[i], pointsym.rot[j])) { goto escape; } } mat_copy_matrix_i3(pointsym.rot[pointsym.size], rotations[i]); pointsym.size++; escape: ; } return pointsym; }
/* Return NULL if failed */ static MatINT *get_point_group_reciprocal(const MatINT * rotations, const int is_time_reversal) { int i, j, num_rot; MatINT *rot_reciprocal, *rot_return; int *unique_rot; SPGCONST int inversion[3][3] = { {-1, 0, 0 }, { 0,-1, 0 }, { 0, 0,-1 } }; rot_reciprocal = NULL; rot_return = NULL; unique_rot = NULL; if (is_time_reversal) { if ((rot_reciprocal = mat_alloc_MatINT(rotations->size * 2)) == NULL) { return NULL; } } else { if ((rot_reciprocal = mat_alloc_MatINT(rotations->size)) == NULL) { return NULL; } } if ((unique_rot = (int*)malloc(sizeof(int) * rot_reciprocal->size)) == NULL) { warning_print("spglib: Memory of unique_rot could not be allocated."); mat_free_MatINT(rot_reciprocal); return NULL; } for (i = 0; i < rot_reciprocal->size; i++) { unique_rot[i] = -1; } for (i = 0; i < rotations->size; i++) { mat_transpose_matrix_i3(rot_reciprocal->mat[i], rotations->mat[i]); if (is_time_reversal) { mat_multiply_matrix_i3(rot_reciprocal->mat[rotations->size+i], inversion, rot_reciprocal->mat[i]); } } num_rot = 0; for (i = 0; i < rot_reciprocal->size; i++) { for (j = 0; j < num_rot; j++) { if (mat_check_identity_matrix_i3(rot_reciprocal->mat[unique_rot[j]], rot_reciprocal->mat[i])) { goto escape; } } unique_rot[num_rot] = i; num_rot++; escape: ; } if ((rot_return = mat_alloc_MatINT(num_rot)) != NULL) { for (i = 0; i < num_rot; i++) { mat_copy_matrix_i3(rot_return->mat[i], rot_reciprocal->mat[unique_rot[i]]); } } free(unique_rot); unique_rot = NULL; mat_free_MatINT(rot_reciprocal); rot_reciprocal = NULL; return rot_return; }
/* Return NULL if failed */ static Symmetry * reduce_operation(SPGCONST Cell * primitive, SPGCONST Symmetry * symmetry, const double symprec, const double angle_symprec) { int i, j, num_sym; Symmetry * sym_reduced; PointSymmetry point_symmetry; MatINT *rot; VecDBL *trans; debug_print("reduce_operation:\n"); sym_reduced = NULL; rot = NULL; trans = NULL; point_symmetry = get_lattice_symmetry(primitive->lattice, symprec, angle_symprec); if (point_symmetry.size == 0) { return NULL; } if ((rot = mat_alloc_MatINT(symmetry->size)) == NULL) { return NULL; } if ((trans = mat_alloc_VecDBL(symmetry->size)) == NULL) { mat_free_MatINT(rot); rot = NULL; return NULL; } num_sym = 0; for (i = 0; i < point_symmetry.size; i++) { for (j = 0; j < symmetry->size; j++) { if (mat_check_identity_matrix_i3(point_symmetry.rot[i], symmetry->rot[j])) { if (is_overlap_all_atoms(symmetry->trans[j], symmetry->rot[j], primitive, symprec, 0)) { mat_copy_matrix_i3(rot->mat[num_sym], symmetry->rot[j]); mat_copy_vector_d3(trans->vec[num_sym], symmetry->trans[j]); num_sym++; } } } } if ((sym_reduced = sym_alloc_symmetry(num_sym)) != NULL) { for (i = 0; i < num_sym; i++) { mat_copy_matrix_i3(sym_reduced->rot[i], rot->mat[i]); mat_copy_vector_d3(sym_reduced->trans[i], trans->vec[i]); } } mat_free_MatINT(rot); rot = NULL; mat_free_VecDBL(trans); trans = NULL; return sym_reduced; }
/* Acta Cryst. (2002). A58, 60-65 */ static int set_exact_location(double position[3], const Symmetry * conv_sym, SPGCONST double bravais_lattice[3][3], const double symprec) { int i, j, k, num_sum, multi, num_pure_trans; double sum_rot[3][3]; double pos[3], sum_trans[3]; debug_print("get_exact_location\n"); num_sum = 0; for (i = 0; i < 3; i++) { sum_trans[i] = 0.0; for (j = 0; j < 3; j++) { sum_rot[i][j] = 0; } } num_pure_trans = 0; for (i = 0; i < conv_sym->size; i++) { if (mat_check_identity_matrix_i3(identity, conv_sym->rot[i])) { num_pure_trans++; for (j = 0; j < 3; j++) { pos[j] = position[j]; } } else { mat_multiply_matrix_vector_id3(pos, conv_sym->rot[i], position); } for (j = 0; j < 3; j++) { pos[j] += conv_sym->trans[i][j]; } if (cel_is_overlap(pos, position, bravais_lattice, symprec)) { for (j = 0; j < 3; j++) { for (k = 0; k < 3; k++) { sum_rot[j][k] += conv_sym->rot[i][j][k]; } sum_trans[j] += conv_sym->trans[i][j] - mat_Nint(pos[j] - position[j]); } num_sum++; } } for (i = 0; i < 3; i++) { sum_trans[i] /= num_sum; for (j = 0; j < 3; j++) { sum_rot[i][j] /= num_sum; } } /* (sum_rot|sum_trans) is the special-position operator. */ /* Elements of sum_rot can be fractional values. */ mat_multiply_matrix_vector_d3(position, sum_rot, position); for (i = 0; i < 3; i++) { position[i] += sum_trans[i]; } multi = conv_sym->size / num_pure_trans / num_sum; if (multi * num_sum * num_pure_trans == conv_sym->size) { return multi; } else { return 0; } }