static PointSymmetry get_lattice_symmetry(SPGCONST Cell *cell, const double symprec) { int i, j, k, num_sym; int axes[3][3]; double lattice[3][3], min_lattice[3][3]; double metric[3][3], metric_orig[3][3]; PointSymmetry lattice_sym; debug_print("get_lattice_symmetry:\n"); if (! lat_smallest_lattice_vector(min_lattice, cell->lattice, symprec)) { goto err; } mat_get_metric(metric_orig, min_lattice); num_sym = 0; for (i = 0; i < 26; i++) { for (j = 0; j < 26; j++) { for (k = 0; k < 26; k++) { set_axes(axes, i, j, k); if (! ((mat_get_determinant_i3(axes) == 1) || (mat_get_determinant_i3(axes) == -1))) { continue; } mat_multiply_matrix_di3(lattice, min_lattice, axes); mat_get_metric(metric, lattice); if (is_identity_metric(metric, metric_orig, symprec)) { mat_copy_matrix_i3(lattice_sym.rot[num_sym], axes); num_sym++; } if (num_sym > 48) { warning_print("spglib: Too many lattice symmetries was found.\n"); warning_print(" Tolerance may be too large "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); goto err; } } } } lattice_sym.size = num_sym; return transform_pointsymmetry(&lattice_sym, cell->lattice, min_lattice); err: lattice_sym.size = 0; return lattice_sym; }
static PointSymmetry get_lattice_symmetry(SPGCONST double cell_lattice[3][3], const double symprec, const double angle_symprec) { int i, j, k, attempt, num_sym; double angle_tol; int axes[3][3]; double lattice[3][3], min_lattice[3][3]; double metric[3][3], metric_orig[3][3]; PointSymmetry lattice_sym; debug_print("get_lattice_symmetry:\n"); lattice_sym.size = 0; if (! del_delaunay_reduce(min_lattice, cell_lattice, symprec)) { goto err; } mat_get_metric(metric_orig, min_lattice); angle_tol = angle_symprec; for (attempt = 0; attempt < 100; attempt++) { num_sym = 0; for (i = 0; i < 26; i++) { for (j = 0; j < 26; j++) { for (k = 0; k < 26; k++) { set_axes(axes, i, j, k); if (! ((mat_get_determinant_i3(axes) == 1) || (mat_get_determinant_i3(axes) == -1))) { continue; } mat_multiply_matrix_di3(lattice, min_lattice, axes); mat_get_metric(metric, lattice); if (is_identity_metric(metric, metric_orig, symprec, angle_tol)) { if (num_sym > 47) { angle_tol *= ANGLE_REDUCE_RATE; warning_print("spglib: Too many lattice symmetries was found.\n"); warning_print(" Reduce angle tolerance to %f", angle_tol); warning_print(" (line %d, %s).\n", __LINE__, __FILE__); goto next_attempt; } mat_copy_matrix_i3(lattice_sym.rot[num_sym], axes); num_sym++; } } } } if (num_sym < 49 || angle_tol < 0) { lattice_sym.size = num_sym; return transform_pointsymmetry(&lattice_sym, cell_lattice, min_lattice); } next_attempt: ; } err: debug_print("get_lattice_symmetry failed.\n"); return lattice_sym; }
/* was not a primitive cell. */ static Symmetry * get_operations(SPGCONST Cell *cell, const double symprec) { int i, j, attempt; double tolerance; PointSymmetry lattice_sym; Symmetry *symmetry, *symmetry_orig, *symmetry_reduced; Primitive primitive; debug_print("get_operations:\n"); symmetry_orig = NULL; lattice_sym = get_lattice_symmetry(cell, symprec); if (lattice_sym.size == 0) { debug_print("get_lattice_symmetry failed.\n"); goto end; } primitive = prm_get_primitive_and_pure_translations(cell, symprec); if (primitive.cell->size == 0) { goto deallocate_and_end; } lattice_sym = transform_pointsymmetry(&lattice_sym, primitive.cell->lattice, cell->lattice); if (lattice_sym.size == 0) { goto deallocate_and_end; } symmetry = get_space_group_operations(&lattice_sym, primitive.cell, symprec); if (symmetry->size > 48) { tolerance = symprec; for (attempt = 0; attempt < 100; attempt++) { tolerance *= REDUCE_RATE; warning_print("spglib: number of symmetry operations for primitive cell > 48 was found. (line %d, %s).\n", __LINE__, __FILE__); warning_print("tolerance is reduced to %f\n", tolerance); symmetry_reduced = reduce_operation(primitive.cell, symmetry, tolerance); sym_free_symmetry(symmetry); symmetry = symmetry_reduced; if (symmetry_reduced->size > 48) { ; } else { break; } } } symmetry_orig = recover_operations_original(symmetry, primitive.pure_trans, cell, primitive.cell); sym_free_symmetry(symmetry); for (i = 0; i < symmetry_orig->size; i++) { for (j = 0; j < 3; j++) { symmetry_orig->trans[i][j] -= mat_Nint(symmetry_orig->trans[i][j]); } } deallocate_and_end: cel_free_cell(primitive.cell); mat_free_VecDBL(primitive.pure_trans); end: if (! symmetry_orig) { symmetry_orig = sym_alloc_symmetry(0); } return symmetry_orig; }
/* was not a primitive cell. */ static int get_operation( int rot[][3][3], double trans[][3], SPGCONST Cell *cell, const double symprec ) { int num_sym; int multi; int *mapping_table; PointSymmetry lattice_sym; Cell *primitive; VecDBL *pure_trans; pure_trans = sym_get_pure_translation(cell, symprec); multi = pure_trans->size; /* Lattice symmetry for input cell*/ lattice_sym = get_lattice_symmetry( cell, symprec ); if ( lattice_sym.size == 0 ) { goto err; } /* Obtain primitive cell */ if( multi > 1 ) { mapping_table = (int*) malloc( sizeof(int) * cell->size ); primitive = prm_get_primitive( mapping_table, cell, pure_trans, symprec ); free( mapping_table ); mapping_table = NULL; if ( primitive->size < 1 ) { goto err; } lattice_sym = transform_pointsymmetry( &lattice_sym, primitive->lattice, cell->lattice ); if ( lattice_sym.size == 0 ) { goto err; } } else { primitive = cell; } /* Symmetry operation search for primitive cell */ num_sym = get_space_group_operation( rot, trans, &lattice_sym, primitive, symprec ); /* Recover symmetry operation for the input structure (overwritten) */ if( multi > 1 ) { num_sym = get_operation_supercell( rot, trans, num_sym, pure_trans, cell, primitive ); cel_free_cell( primitive ); if ( num_sym == 0 ) { goto err; } } mat_free_VecDBL( pure_trans ); return num_sym; err: mat_free_VecDBL( pure_trans ); return 0; }