static void search_translation_part(int lat_point_atoms[], SPGCONST Cell * cell, SPGCONST int rot[3][3], const int min_atom_index, const double origin[3], const double symprec, const int is_identity) { int i, j; double vec[3]; for (i = 0; i < cell->size; i++) { if (cell->types[i] != cell->types[min_atom_index]) { continue; } for (j = 0; j < 3; j++) { vec[j] = cell->position[i][j] - origin[j]; } if (is_overlap_all_atoms(vec, rot, cell, symprec, is_identity)) { lat_point_atoms[i] = 1; } } }
/* This function is heaviest in this code. */ static VecDBL * get_translation( SPGCONST int rot[3][3], SPGCONST Cell *cell, const double symprec, const int is_identity ) { int i, j, min_atom_index, num_trans = 0; int *is_found; double origin[3]; VecDBL *tmp_trans, *trans; tmp_trans = mat_alloc_VecDBL( cell->size ); is_found = (int*) malloc( sizeof(int)*cell->size); for ( i = 0; i < cell->size; i++ ) { is_found[i] = 0; } /* Look for the atom index with least number of atoms within same type */ min_atom_index = get_index_with_least_atoms( cell ); /* Set min_atom_index as the origin to measure the distance between atoms. */ mat_multiply_matrix_vector_id3(origin, rot, cell->position[min_atom_index]); #pragma omp parallel for private( j ) for (i = 0; i < cell->size; i++) { /* test translation */ if (cell->types[i] != cell->types[min_atom_index]) { continue; } for (j = 0; j < 3; j++) { tmp_trans->vec[i][j] = cell->position[i][j] - origin[j]; } if ( is_overlap_all_atoms( tmp_trans->vec[i], rot, cell, symprec, is_identity ) ) { is_found[i] = 1; } } for ( i = 0; i < cell->size; i++ ) { num_trans += is_found[i]; } trans = mat_alloc_VecDBL( num_trans ); num_trans = 0; for ( i = 0; i < cell->size; i++ ) { if ( is_found[i] ) { mat_copy_vector_d3( trans->vec[num_trans], tmp_trans->vec[i] ); num_trans++; } } mat_free_VecDBL( tmp_trans ); free( is_found ); is_found = NULL; return trans; }
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; }
/* This function is heaviest in this code. */ static VecDBL * get_translation(SPGCONST int rot[3][3], SPGCONST Cell *cell, const double symprec, const int is_identity) { int i, j, min_atom_index, num_trans = 0; int *is_found; double origin[3]; VecDBL *trans; #ifdef _OPENMP int num_min_type_atoms; int *min_type_atoms; double vec[3]; #endif is_found = (int*) malloc(sizeof(int)*cell->size); for (i = 0; i < cell->size; i++) { is_found[i] = 0; } /* Look for the atom index with least number of atoms within same type */ min_atom_index = get_index_with_least_atoms(cell); /* Set min_atom_index as the origin to measure the distance between atoms. */ mat_multiply_matrix_vector_id3(origin, rot, cell->position[min_atom_index]); #ifdef _OPENMP if (cell->size < NUM_ATOMS_CRITERION_FOR_OPENMP) { search_translation_part(is_found, cell, rot, min_atom_index, origin, symprec, is_identity); } else { /* Collect indices of atoms with the type where the minimum number */ /* of atoms belong. */ min_type_atoms = (int*) malloc(sizeof(int)*cell->size); num_min_type_atoms = 0; for (i = 0; i < cell->size; i++) { if (cell->types[i] == cell->types[min_atom_index]) { min_type_atoms[num_min_type_atoms] = i; num_min_type_atoms++; } } #pragma omp parallel for private(j, vec) for (i = 0; i < num_min_type_atoms; i++) { for (j = 0; j < 3; j++) { vec[j] = cell->position[min_type_atoms[i]][j] - origin[j]; } if (is_overlap_all_atoms(vec, rot, cell, symprec, is_identity)) { is_found[min_type_atoms[i]] = 1; } } free(min_type_atoms); } #else search_translation_part(is_found, cell, rot, min_atom_index, origin, symprec, is_identity); #endif for (i = 0; i < cell->size; i++) { num_trans += is_found[i]; } trans = mat_alloc_VecDBL(num_trans); num_trans = 0; for (i = 0; i < cell->size; i++) { if (is_found[i]) { for (j = 0; j < 3; j++) { trans->vec[num_trans][j] = cell->position[i][j] - origin[j]; } num_trans++; } } free(is_found); is_found = NULL; return trans; }
/* Return NULL if failed */ static VecDBL * get_translation(SPGCONST int rot[3][3], SPGCONST Cell *cell, const double symprec, const int is_identity) { int i, j, k, min_atom_index, num_trans; int *is_found; double origin[3]; VecDBL *trans; debug_print("get_translation (tolerance = %f):\n", symprec); num_trans = 0; is_found = NULL; trans = NULL; #ifdef _OPENMP int num_min_type_atoms; int *min_type_atoms; double vec[3]; min_type_atoms = NULL; #endif if ((is_found = (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[i] = 0; } /* Look for the atom index with least number of atoms within same type */ min_atom_index = get_index_with_least_atoms(cell); if (min_atom_index == -1) { debug_print("spglib: get_index_with_least_atoms failed.\n"); goto ret; } /* Set min_atom_index as the origin to measure the distance between atoms. */ mat_multiply_matrix_vector_id3(origin, rot, cell->position[min_atom_index]); #ifdef _OPENMP if (cell->size < NUM_ATOMS_CRITERION_FOR_OPENMP) { num_trans = search_translation_part(is_found, cell, rot, min_atom_index, origin, symprec, is_identity); if (num_trans == 0) { goto ret; } } else { /* Collect indices of atoms with the type where the minimum number */ /* of atoms belong. */ if ((min_type_atoms = (int*) malloc(sizeof(int)*cell->size)) == NULL) { warning_print("spglib: Memory could not be allocated "); goto ret; } num_min_type_atoms = 0; for (i = 0; i < cell->size; i++) { if (cell->types[i] == cell->types[min_atom_index]) { min_type_atoms[num_min_type_atoms] = i; num_min_type_atoms++; } } #pragma omp parallel for private(j, vec) for (i = 0; i < num_min_type_atoms; i++) { for (j = 0; j < 3; j++) { vec[j] = cell->position[min_type_atoms[i]][j] - origin[j]; } if (is_overlap_all_atoms(vec, rot, cell, symprec, is_identity)) { is_found[min_type_atoms[i]] = 1; } } free(min_type_atoms); min_type_atoms = NULL; for (i = 0; i < cell->size; i++) { num_trans += is_found[i]; } } #else num_trans = search_translation_part(is_found, cell, rot, min_atom_index, origin, symprec, is_identity); if (num_trans == 0) { goto ret; } #endif if ((trans = mat_alloc_VecDBL(num_trans)) == NULL) { goto ret; } k = 0; for (i = 0; i < cell->size; i++) { if (is_found[i]) { for (j = 0; j < 3; j++) { trans->vec[k][j] = cell->position[i][j] - origin[j]; } k++; } } ret: free(is_found); is_found = NULL; return trans; }
/* 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; }