static MatINT *get_point_group_reciprocal_with_q(const MatINT * rot_reciprocal, const double symprec, const int num_q, SPGCONST double qpoints[][3]) { int i, j, k, l, is_all_ok, num_rot; int *ir_rot; double q_rot[3], diff[3]; MatINT * rot_reciprocal_q; is_all_ok = 0; num_rot = 0; ir_rot = (int*)malloc(sizeof(int) * rot_reciprocal->size); for (i = 0; i < rot_reciprocal->size; i++) { ir_rot[i] = -1; } for (i = 0; i < rot_reciprocal->size; i++) { for (j = 0; j < num_q; j++) { is_all_ok = 0; mat_multiply_matrix_vector_id3(q_rot, rot_reciprocal->mat[i], qpoints[j]); for (k = 0; k < num_q; k++) { for (l = 0; l < 3; l++) { diff[l] = q_rot[l] - qpoints[k][l]; diff[l] -= mat_Nint(diff[l]); } if (mat_Dabs(diff[0]) < symprec && mat_Dabs(diff[1]) < symprec && mat_Dabs(diff[2]) < symprec) { is_all_ok = 1; break; } } if (! is_all_ok) { break; } } if (is_all_ok) { ir_rot[num_rot] = i; num_rot++; } } rot_reciprocal_q = mat_alloc_MatINT(num_rot); for (i = 0; i < num_rot; i++) { mat_copy_matrix_i3(rot_reciprocal_q->mat[i], rot_reciprocal->mat[ir_rot[i]]); } free(ir_rot); return rot_reciprocal_q; }
static int is_identity_metric(SPGCONST double metric_rotated[3][3], SPGCONST double metric_orig[3][3], const double symprec, const double angle_symprec) { int i, j, k; int elem_sets[3][2] = {{0, 1}, {0, 2}, {1, 2}}; double cos1, cos2, x, length_ave2, sin_dtheta2; double length_orig[3], length_rot[3]; for (i = 0; i < 3; i++) { length_orig[i] = sqrt(metric_orig[i][i]); length_rot[i] = sqrt(metric_rotated[i][i]); if (mat_Dabs(length_orig[i] - length_rot[i]) > symprec) { goto fail; } } for (i = 0; i < 3; i++) { j = elem_sets[i][0]; k = elem_sets[i][1]; if (angle_symprec > 0) { if (mat_Dabs(get_angle(metric_orig, j, k) - get_angle(metric_rotated, j, k)) > angle_symprec) { goto fail; } } else { /* dtheta = arccos(cos(theta1) - arccos(cos(theta2))) */ /* = arccos(c1) - arccos(c2) */ /* = arccos(c1c2 + sqrt((1-c1^2)(1-c2^2))) */ /* sin(dtheta) = sin(arccos(x)) = sqrt(1 - x^2) */ cos1 = metric_orig[j][k] / length_orig[j] / length_orig[k]; cos2 = metric_rotated[j][k] / length_rot[j] / length_rot[k]; x = cos1 * cos2 + sqrt(1 - cos1 * cos1) * sqrt(1 - cos2 * cos2); sin_dtheta2 = 1 - x * x; length_ave2 = ((length_orig[j] + length_rot[j]) * (length_orig[k] + length_rot[k])) / 4; if (sin_dtheta2 > 1e-12) { if (sin_dtheta2 * length_ave2 > symprec * symprec) { goto fail; } } } } return 1; fail: return 0; }
/* }} */ int mat_inverse_matrix_d3(double m[3][3], SPGCONST double a[3][3], const double precision) { double det; double c[3][3]; det = mat_get_determinant_d3(a); if (mat_Dabs(det) < precision) { warning_print("spglib: No inverse matrix (det=%f)\n", det); debug_print("No inverse matrix\n"); return 0; } c[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det; c[1][0] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) / det; c[2][0] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det; c[0][1] = (a[2][1] * a[0][2] - a[2][2] * a[0][1]) / det; c[1][1] = (a[2][2] * a[0][0] - a[2][0] * a[0][2]) / det; c[2][1] = (a[2][0] * a[0][1] - a[2][1] * a[0][0]) / det; c[0][2] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det; c[1][2] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) / det; c[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det; mat_copy_matrix_d3(m, c); return 1; }
static PointSymmetry get_point_group_reciprocal_with_q(SPGCONST PointSymmetry * pointgroup, const double symprec, const int num_q, SPGCONST double qpoints[][3]) { int i, j, k, l, is_all_ok=0, num_ptq = 0; double q_rot[3], diff[3]; PointSymmetry pointgroup_q; for (i = 0; i < pointgroup->size; i++) { for (j = 0; j < num_q; j++) { is_all_ok = 0; mat_multiply_matrix_vector_id3(q_rot, pointgroup->rot[i], qpoints[j]); for (k = 0; k < num_q; k++) { for (l = 0; l < 3; l++) { diff[l] = q_rot[l] - qpoints[k][l]; diff[l] -= mat_Nint(diff[l]); } if (mat_Dabs(diff[0]) < symprec && mat_Dabs(diff[1]) < symprec && mat_Dabs(diff[2]) < symprec) { is_all_ok = 1; break; } } if (! is_all_ok) { break; } } if (is_all_ok) { mat_copy_matrix_i3(pointgroup_q.rot[num_ptq], pointgroup->rot[i]); num_ptq++; } } pointgroup_q.size = num_ptq; return pointgroup_q; }
/* Reference can be found in International table A. */ static int get_Delaunay_reduction( double red_lattice[3][3], SPGCONST double lattice[3][3], const double symprec ) { int i, j; double volume; double basis[4][3]; get_exteneded_basis(basis, lattice); while (1) { if (get_Delaunay_reduction_basis(basis, symprec)) { break; } } get_Delaunay_shortest_vectors( basis, symprec ); for ( i = 0; i < 3; i++ ) { for ( j = 0; j < 3; j++ ) { red_lattice[i][j] = basis[j][i]; } } volume = mat_get_determinant_d3( red_lattice ); if ( mat_Dabs( volume ) < symprec ) { warning_print("spglib: Minimum lattice has no volume (line %d, %s).\n", __LINE__, __FILE__); goto err; } if ( volume < 0 ) { /* Flip axes */ for (i = 0; i < 3; i++) { for ( j = 0; j < 3; j++ ) { red_lattice[i][j] = -red_lattice[i][j]; } } } #ifdef DEBUG debug_print("Delaunay reduction:\n"); debug_print_matrix_d3(red_lattice); double metric[3][3]; mat_get_metric( metric, red_lattice ); debug_print("It's metric tensor.\n"); debug_print_matrix_d3( metric ); #endif return 1; err: return 0; }
int mat_is_int_matrix(SPGCONST double mat[3][3], const double symprec) { int i,j ; for ( i = 0; i < 3; i++ ) { for ( j = 0; j < 3; j++ ) { if ( mat_Dabs( mat_Nint( mat[i][j] ) - mat[i][j] ) > symprec ) { return 0; } } } return 1; }
/* Return 0 if failed */ static int get_Delaunay_reduction(double red_lattice[3][3], SPGCONST double lattice[3][3], const double symprec) { int i, j; double volume, sum; double basis[4][3]; get_exteneded_basis(basis, lattice); sum = 0; for (i = 0; i < 4; i++) { for (j = 0; j < 3; j++) { sum += basis[i][j] * basis[i][j]; } } while (1) { if (get_Delaunay_reduction_basis(basis, symprec)) { break; } } get_Delaunay_shortest_vectors(basis, symprec); for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { red_lattice[i][j] = basis[j][i]; } } volume = mat_get_determinant_d3(red_lattice); if (mat_Dabs(volume) < symprec) { warning_print("spglib: Minimum lattice has no volume (line %d, %s).\n", __LINE__, __FILE__); goto err; } if (volume < 0) { /* Flip axes */ for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { red_lattice[i][j] = -red_lattice[i][j]; } } } return 1; err: return 0; }
int mat_check_identity_matrix_d3(SPGCONST double a[3][3], SPGCONST double b[3][3], const double symprec) { if ( mat_Dabs( a[0][0] - b[0][0] ) > symprec || mat_Dabs( a[0][1] - b[0][1] ) > symprec || mat_Dabs( a[0][2] - b[0][2] ) > symprec || mat_Dabs( a[1][0] - b[1][0] ) > symprec || mat_Dabs( a[1][1] - b[1][1] ) > symprec || mat_Dabs( a[1][2] - b[1][2] ) > symprec || mat_Dabs( a[2][0] - b[2][0] ) > symprec || mat_Dabs( a[2][1] - b[2][1] ) > symprec || mat_Dabs( a[2][2] - b[2][2] ) > symprec ) { return 0; } else { return 1; } }
static void get_Delaunay_shortest_vectors( double basis[4][3], const double symprec ) { int i, j; double tmpmat[3][3], b[7][3], tmpvec[3]; /* Search in the set {b1, b2, b3, b4, b1+b2, b2+b3, b3+b1} */ for ( i = 0; i < 4; i++ ) { for ( j = 0; j < 3; j++ ) { b[i][j] = basis[i][j]; } } for ( i = 0; i < 3; i++ ) { b[4][i] = basis[0][i] + basis[1][i]; } for ( i = 0; i < 3; i++ ) { b[5][i] = basis[1][i] + basis[2][i]; } for ( i = 0; i < 3; i++ ) { b[6][i] = basis[2][i] + basis[0][i]; } /* Bubble sort */ for ( i = 0; i < 6; i++ ) { for ( j = 0; j < 6; j++ ) { if ( mat_norm_squared_d3( b[j] ) > mat_norm_squared_d3( b[j+1] ) ) { mat_copy_vector_d3( tmpvec, b[j] ); mat_copy_vector_d3( b[j], b[j+1] ); mat_copy_vector_d3( b[j+1], tmpvec ); } } } for ( i = 2; i < 7; i++ ) { for ( j = 0; j < 3; j++ ) { tmpmat[j][0] = b[0][j]; tmpmat[j][1] = b[1][j]; tmpmat[j][2] = b[i][j]; } if ( mat_Dabs( mat_get_determinant_d3( tmpmat ) ) > symprec ) { for ( j = 0; j < 3; j++ ) { basis[0][j] = b[0][j]; basis[1][j] = b[1][j]; basis[2][j] = b[i][j]; } break; } } }
static PointSymmetry transform_pointsymmetry(SPGCONST PointSymmetry * lat_sym_orig, SPGCONST double new_lattice[3][3], SPGCONST double original_lattice[3][3]) { int i, size; double trans_mat[3][3], inv_mat[3][3], drot[3][3]; PointSymmetry lat_sym_new; lat_sym_new.size = 0; mat_inverse_matrix_d3(inv_mat, original_lattice, 0); mat_multiply_matrix_d3(trans_mat, inv_mat, new_lattice); size = 0; for (i = 0; i < lat_sym_orig->size; i++) { mat_cast_matrix_3i_to_3d(drot, lat_sym_orig->rot[i]); mat_get_similar_matrix_d3(drot, drot, trans_mat, 0); /* new_lattice may have lower point symmetry than original_lattice.*/ /* The operations that have non-integer elements are not counted. */ if (mat_is_int_matrix(drot, mat_Dabs(mat_get_determinant_d3(trans_mat)) / 10)) { mat_cast_matrix_3d_to_3i(lat_sym_new.rot[size], drot); if (abs(mat_get_determinant_i3(lat_sym_new.rot[size])) != 1) { warning_print("spglib: A point symmetry operation is not unimodular."); warning_print("(line %d, %s).\n", __LINE__, __FILE__); goto err; } size++; } } #ifdef SPGWARNING if (! (lat_sym_orig->size == size)) { warning_print("spglib: Some of point symmetry operations were dropped."); warning_print("(line %d, %s).\n", __LINE__, __FILE__); } #endif lat_sym_new.size = size; return lat_sym_new; err: return lat_sym_new; }
static void set_positions(Cell * trimmed_cell, const VecDBL * position, const int * mapping_table, const int * overlap_table) { int i, j, k, l, multi; for (i = 0; i < trimmed_cell->size; i++) { for (j = 0; j < 3; j++) { trimmed_cell->position[i][j] = 0; } } /* Positions of overlapped atoms are averaged. */ for (i = 0; i < position->size; i++) { j = mapping_table[i]; k = overlap_table[i]; for (l = 0; l < 3; l++) { /* boundary treatment */ /* One is at right and one is at left or vice versa. */ if (mat_Dabs(position->vec[k][l] - position->vec[i][l]) > 0.5) { if (position->vec[i][l] < position->vec[k][l]) { trimmed_cell->position[j][l] += position->vec[i][l] + 1; } else { trimmed_cell->position[j][l] += position->vec[i][l] - 1; } } else { trimmed_cell->position[j][l] += position->vec[i][l]; } } } multi = position->size / trimmed_cell->size; for (i = 0; i < trimmed_cell->size; i++) { for (j = 0; j < 3; j++) { trimmed_cell->position[i][j] /= multi; trimmed_cell->position[i][j] = mat_Dmod1(trimmed_cell->position[i][j]); } } }
/* }} */ int mat_inverse_matrix_d3(double m[3][3], const double a[3][3], const double precision) { double det; double c[3][3]; det = mat_get_determinant_d3(a); if (mat_Dabs(det) < precision) { fprintf(stderr, "spglib: No inverse matrix\n"); return 0; } c[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det; c[1][0] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) / det; c[2][0] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det; c[0][1] = (a[2][1] * a[0][2] - a[2][2] * a[0][1]) / det; c[1][1] = (a[2][2] * a[0][0] - a[2][0] * a[0][2]) / det; c[2][1] = (a[2][0] * a[0][1] - a[2][1] * a[0][0]) / det; c[0][2] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det; c[1][2] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) / det; c[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det; mat_copy_matrix_d3(m, c); return 1; }
static Symmetry * get_collinear_operations(SPGCONST Symmetry *sym_nonspin, SPGCONST Cell *cell, const double spins[], const double symprec) { Symmetry *symmetry; int i, j, k, sign, is_found, num_sym; double pos[3]; MatINT * rot; VecDBL * trans; rot = mat_alloc_MatINT(sym_nonspin->size); trans = mat_alloc_VecDBL(sym_nonspin->size); num_sym = 0; for (i = 0; i < sym_nonspin->size; i++) { sign = 0; /* Set sign as undetermined */ is_found = 1; for (j = 0; j < cell->size; j++) { mat_multiply_matrix_vector_id3(pos, sym_nonspin->rot[i], cell->position[j]); for (k = 0; k < 3; k++) { pos[k] += sym_nonspin->trans[i][k]; } for (k = 0; k < cell->size; k++) { if (cel_is_overlap(cell->position[k], pos, cell->lattice, symprec)) { if (sign == 0) { if (mat_Dabs(spins[j] - spins[k]) < symprec) { sign = 1; break; } if (mat_Dabs(spins[j] + spins[k]) < symprec) { sign = -1; break; } is_found = 0; break; } else { if (mat_Dabs(spins[j] - spins[k] * sign) < symprec) { break; } else { is_found = 0; break; } } } } if (! is_found) { break; } } if (is_found) { mat_copy_matrix_i3(rot->mat[num_sym], sym_nonspin->rot[i]); mat_copy_vector_d3(trans->vec[num_sym], sym_nonspin->trans[i]); num_sym++; } } symmetry = sym_alloc_symmetry(num_sym); for (i = 0; i < num_sym; i++) { mat_copy_matrix_i3(symmetry->rot[i], rot->mat[ i ]); mat_copy_vector_d3(symmetry->trans[i], trans->vec[ i ]); } mat_free_MatINT(rot); mat_free_VecDBL(trans); return symmetry; }
/* Return 0 if failed */ static int get_primitive_lattice_vectors(double prim_lattice[3][3], const VecDBL * vectors, SPGCONST Cell * cell, const double symprec) { int i, j, k, size; double initial_volume, volume; double relative_lattice[3][3], min_vectors[3][3], tmp_lattice[3][3]; double inv_mat_dbl[3][3]; int inv_mat_int[3][3]; debug_print("get_primitive_lattice_vectors:\n"); size = vectors->size; initial_volume = mat_Dabs(mat_get_determinant_d3(cell->lattice)); /* check volumes of all possible lattices, find smallest volume */ for (i = 0; i < size; i++) { for (j = i + 1; j < size; j++) { for (k = j + 1; k < size; k++) { mat_multiply_matrix_vector_d3(tmp_lattice[0], cell->lattice, vectors->vec[i]); mat_multiply_matrix_vector_d3(tmp_lattice[1], cell->lattice, vectors->vec[j]); mat_multiply_matrix_vector_d3(tmp_lattice[2], cell->lattice, vectors->vec[k]); volume = mat_Dabs(mat_get_determinant_d3(tmp_lattice)); if (volume > symprec) { if (mat_Nint(initial_volume / volume) == size-2) { mat_copy_vector_d3(min_vectors[0], vectors->vec[i]); mat_copy_vector_d3(min_vectors[1], vectors->vec[j]); mat_copy_vector_d3(min_vectors[2], vectors->vec[k]); goto ret; } } } } } /* Not found */ warning_print("spglib: Primitive lattice vectors cound not be found "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); return 0; /* Found */ ret: for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { relative_lattice[j][i] = min_vectors[i][j]; } } mat_inverse_matrix_d3(inv_mat_dbl, relative_lattice, 0); mat_cast_matrix_3d_to_3i(inv_mat_int, inv_mat_dbl); if (abs(mat_get_determinant_i3(inv_mat_int)) == size-2) { mat_cast_matrix_3i_to_3d(inv_mat_dbl, inv_mat_int); mat_inverse_matrix_d3(relative_lattice, inv_mat_dbl, 0); } else { warning_print("spglib: Primitive lattice cleaning is incomplete "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); } mat_multiply_matrix_d3(prim_lattice, cell->lattice, relative_lattice); return 1; }
static int get_ir_kpoints(int map[], SPGCONST double kpoints[][3], const int num_kpoint, SPGCONST PointSymmetry * point_symmetry, const double symprec) { int i, j, k, l, num_ir_kpoint = 0, is_found; int *ir_map; double kpt_rot[3], diff[3]; ir_map = (int*)malloc(num_kpoint*sizeof(int)); for (i = 0; i < num_kpoint; i++) { map[i] = i; is_found = 1; for (j = 0; j < point_symmetry->size; j++) { mat_multiply_matrix_vector_id3(kpt_rot, point_symmetry->rot[j], kpoints[i]); for (k = 0; k < 3; k++) { diff[k] = kpt_rot[k] - kpoints[i][k]; diff[k] = diff[k] - mat_Nint(diff[k]); } if (mat_Dabs(diff[0]) < symprec && mat_Dabs(diff[1]) < symprec && mat_Dabs(diff[2]) < symprec) { continue; } for (k = 0; k < num_ir_kpoint; k++) { mat_multiply_matrix_vector_id3(kpt_rot, point_symmetry->rot[j], kpoints[i]); for (l = 0; l < 3; l++) { diff[l] = kpt_rot[l] - kpoints[ir_map[k]][l]; diff[l] = diff[l] - mat_Nint(diff[l]); } if (mat_Dabs(diff[0]) < symprec && mat_Dabs(diff[1]) < symprec && mat_Dabs(diff[2]) < symprec) { is_found = 0; map[i] = ir_map[k]; break; } } if (! is_found) break; } if (is_found) { ir_map[num_ir_kpoint] = i; num_ir_kpoint++; } } free(ir_map); ir_map = NULL; return num_ir_kpoint; }
/* Return 0 if failed */ static int set_primitive_positions(Cell * primitive_cell, const VecDBL * position, const Cell * cell, int * const * table) { int i, j, k, ratio, index_prim_atom; int *is_equivalent; is_equivalent = NULL; if ((is_equivalent = (int*) malloc(cell->size * sizeof(int))) == NULL) { warning_print("spglib: Memory could not be allocated "); goto err; } for (i = 0; i < cell->size; i++) { is_equivalent[i] = 0; } ratio = cell->size / primitive_cell->size; /* Copy positions. Positions of overlapped atoms are averaged. */ index_prim_atom = 0; for (i = 0; i < cell->size; i++) { if (! is_equivalent[i]) { primitive_cell->types[index_prim_atom] = cell->types[i]; for (j = 0; j < 3; j++) { primitive_cell->position[index_prim_atom][j] = 0; } for (j = 0; j < ratio; j++) { /* Loop for averaging positions */ is_equivalent[table[i][j]] = 1; for (k = 0; k < 3; k++) { /* boundary treatment */ /* One is at right and one is at left or vice versa. */ if (mat_Dabs(position->vec[table[i][0]][k] - position->vec[table[i][j]][k]) > 0.5) { if (position->vec[table[i][j]][k] < 0) { primitive_cell->position[index_prim_atom][k] = primitive_cell->position[index_prim_atom][k] + position->vec[table[i][j]][k] + 1; } else { primitive_cell->position[index_prim_atom][k] = primitive_cell->position[index_prim_atom][k] + position->vec[table[i][j]][k] - 1; } } else { primitive_cell->position[index_prim_atom][k] = primitive_cell->position[index_prim_atom][k] + position->vec[table[i][j]][k]; } } } for (j = 0; j < 3; j++) { /* take average and reduce */ primitive_cell->position[index_prim_atom][j] = primitive_cell->position[index_prim_atom][j] / ratio; primitive_cell->position[index_prim_atom][j] = primitive_cell->position[index_prim_atom][j] - mat_Nint(primitive_cell->position[index_prim_atom][j]); } index_prim_atom++; } } free(is_equivalent); is_equivalent = NULL; if (! (index_prim_atom == primitive_cell->size)) { warning_print("spglib: Atomic positions of primitive cell could not be determined "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); goto err; } return 1; err: return 0; }
static int get_Delaunay_reduction_2D(double red_lattice[3][3], SPGCONST double lattice[3][3], const int unique_axis, const double symprec) { int i, j, k; double volume; double basis[3][3], lattice_2D[3][2], unique_vec[3]; k = 0; for (i = 0; i < 3; i++) { unique_vec[i] = lattice[i][unique_axis]; } for (i = 0; i < 3; i++) { if (i != unique_axis) { for (j = 0; j < 3; j++) { lattice_2D[j][k] = lattice[j][i]; } k++; } } get_exteneded_basis_2D(basis, lattice_2D); while (1) { if (get_Delaunay_reduction_basis_2D(basis, symprec)) { break; } } get_Delaunay_shortest_vectors_2D(basis, unique_vec, symprec); k = 0; for (i = 0; i < 3; i++) { if (i == unique_axis) { for (j = 0; j < 3; j++) { red_lattice[j][i] = lattice[j][i]; } } else { for (j = 0; j < 3; j++) { red_lattice[j][i] = basis[k][j]; } k++; } } volume = mat_get_determinant_d3(red_lattice); if (mat_Dabs(volume) < symprec) { warning_print("spglib: Minimum lattice has no volume (line %d, %s).\n", __LINE__, __FILE__); goto err; } if (volume < 0) { for (i = 0; i < 3; i++) { red_lattice[i][unique_axis] = -red_lattice[i][unique_axis]; } } return 1; err: return 0; }
static int set_primitive_positions( Cell * primitive, const VecDBL * position, const Cell * cell, int * const * table ) { int i, j, k, ratio, count; int *is_equivalent = (int*)malloc(cell->size * sizeof(int)); ratio = cell->size / primitive->size; for (i = 0; i < cell->size; i++) { is_equivalent[i] = 0; } /* Copy positions. Positions of overlapped atoms are averaged. */ count = 0; for ( i = 0; i < cell->size; i++ ) if ( ! is_equivalent[i] ) { debug_print("Trimming... i=%d count=%d\n", i, count); primitive->types[count] = cell->types[i]; for ( j = 0; j < 3; j++ ) { primitive->position[count][j] = 0; } for ( j = 0; j < ratio; j++ ) { /* overlap atoms */ if ( table[i][j] < 0 ) { /* check if table is correctly bulit. */ break; } is_equivalent[table[i][j]] = 1; for (k = 0; k < 3; k++) { /* boundary treatment */ if (mat_Dabs(position->vec[table[i][0]][k] - position->vec[table[i][j]][k]) > 0.5) { if (position->vec[table[i][j]][k] < 0) { primitive->position[count][k] = primitive->position[count][k] + position->vec[table[i][j]][k] + 1; } else { primitive->position[count][k] = primitive->position[count][k] + position->vec[table[i][j]][k] - 1; } } else { primitive->position[count][k] = primitive->position[count][k] + position->vec[table[i][j]][k]; } } } for (j = 0; j < 3; j++) { /* take average and reduce */ primitive->position[count][j] = primitive->position[count][j] / ratio; primitive->position[count][j] = primitive->position[count][j] - mat_Nint( primitive->position[count][j] ); } count++; } free(is_equivalent); is_equivalent = NULL; debug_print("Count: %d Size of cell: %d Size of primitive: %d\n", count, cell->size, primitive->size); if ( ! ( count == primitive->size ) ) { warning_print("spglib: Atomic positions of primitive cell could not be determined "); warning_print("(line %d, %s).\n", __LINE__, __FILE__); goto err; } return 1; err: return 0; }