static Symmetry * get_refined_symmetry_operations(SPGCONST Cell * cell, SPGCONST Cell * primitive, SPGCONST Spacegroup * spacegroup, const double symprec) { int t_mat_int[3][3]; int frame[3]; double inv_mat[3][3], t_mat[3][3]; Symmetry *conv_sym, *prim_sym, *symmetry; /* Primitive symmetry from database */ conv_sym = get_db_symmetry(spacegroup->hall_number); set_translation_with_origin_shift(conv_sym, spacegroup->origin_shift); mat_inverse_matrix_d3(inv_mat, primitive->lattice, symprec); mat_multiply_matrix_d3(t_mat, inv_mat, spacegroup->bravais_lattice); prim_sym = get_primitive_db_symmetry(t_mat, conv_sym, symprec); /* Input cell symmetry from primitive symmetry */ mat_inverse_matrix_d3(inv_mat, primitive->lattice, symprec); mat_multiply_matrix_d3(t_mat, inv_mat, cell->lattice); mat_cast_matrix_3d_to_3i(t_mat_int, t_mat); get_surrounding_frame(frame, t_mat_int); symmetry = reduce_symmetry_in_frame(frame, prim_sym, t_mat_int, cell->lattice, cell->size / primitive->size, symprec); /* sym_free_symmetry(f_sym); */ sym_free_symmetry(prim_sym); sym_free_symmetry(conv_sym); return symmetry; }
static int get_operation_supercell( int rot[][3][3], double trans[][3], const int num_sym, const VecDBL * pure_trans, SPGCONST Cell *cell, SPGCONST Cell *primitive ) { int i, j, k, multi; double inv_prim_lat[3][3], drot[3][3], trans_mat[3][3], trans_mat_inv[3][3]; MatINT *rot_prim; VecDBL *trans_prim; rot_prim = mat_alloc_MatINT( num_sym ); trans_prim = mat_alloc_VecDBL( num_sym ); multi = pure_trans->size; debug_print("get_operation_supercell\n"); mat_inverse_matrix_d3( inv_prim_lat, primitive->lattice, 0 ); mat_multiply_matrix_d3( trans_mat, inv_prim_lat, cell->lattice ); mat_inverse_matrix_d3( trans_mat_inv, trans_mat, 0 ); for( i = 0; i < num_sym; i++) { /* Translations */ mat_multiply_matrix_vector_d3( trans[i], trans_mat_inv, trans[i] ); /* Rotations */ mat_cast_matrix_3i_to_3d( drot, rot[i] ); mat_get_similar_matrix_d3( drot, drot, trans_mat, 0 ); mat_cast_matrix_3d_to_3i( rot[i], drot ); } for( i = 0; i < num_sym; i++ ) { mat_copy_matrix_i3( rot_prim->mat[i], rot[i] ); for( j = 0; j < 3; j++ ) trans_prim->vec[i][j] = trans[i][j]; } /* Rotations and translations are copied with the set of */ /* pure translations. */ for( i = 0; i < num_sym; i++ ) { for( j = 0; j < multi; j++ ) { mat_copy_matrix_i3( rot[ i * multi + j ], rot_prim->mat[i] ); for ( k = 0; k < 3; k++ ) { trans[i * multi + j][k] = mat_Dmod1( trans_prim->vec[i][k] + pure_trans->vec[j][k] ); } } } mat_free_MatINT( rot_prim ); mat_free_VecDBL( trans_prim ); /* return number of symmetry operation of supercell */ return num_sym * multi; }
static Symmetry * recover_operations_original(SPGCONST Symmetry *symmetry, const VecDBL * pure_trans, SPGCONST Cell *cell, SPGCONST Cell *primitive) { int i, j, k, multi; double inv_prim_lat[3][3], drot[3][3], trans_mat[3][3], trans_mat_inv[3][3]; Symmetry *symmetry_orig, *sym_tmp; debug_print("recover_operations_original:\n"); multi = pure_trans->size; sym_tmp = sym_alloc_symmetry(symmetry->size); symmetry_orig = sym_alloc_symmetry(symmetry->size * multi); mat_inverse_matrix_d3(inv_prim_lat, primitive->lattice, 0); mat_multiply_matrix_d3(trans_mat, inv_prim_lat, cell->lattice); mat_inverse_matrix_d3(trans_mat_inv, trans_mat, 0); for(i = 0; i < symmetry->size; i++) { mat_copy_matrix_i3(sym_tmp->rot[i], symmetry->rot[i]); mat_copy_vector_d3(sym_tmp->trans[i], symmetry->trans[i]); } for(i = 0; i < symmetry->size; i++) { mat_cast_matrix_3i_to_3d(drot, sym_tmp->rot[i]); mat_get_similar_matrix_d3(drot, drot, trans_mat, 0); mat_cast_matrix_3d_to_3i(sym_tmp->rot[i], drot); mat_multiply_matrix_vector_d3(sym_tmp->trans[i], trans_mat_inv, sym_tmp->trans[i]); } for(i = 0; i < symmetry->size; i++) { for(j = 0; j < multi; j++) { mat_copy_matrix_i3(symmetry_orig->rot[i * multi + j], sym_tmp->rot[i]); for (k = 0; k < 3; k++) { symmetry_orig->trans[i * multi + j][k] = sym_tmp->trans[i][k] + pure_trans->vec[j][k]; } } } sym_free_symmetry(sym_tmp); return symmetry_orig; }
static Cell * get_cell_with_smallest_lattice( SPGCONST Cell * cell, const double symprec ) { int i, j; double min_lat[3][3], trans_mat[3][3], inv_lat[3][3]; Cell * smallest_cell; if ( lat_smallest_lattice_vector( min_lat, cell->lattice, symprec ) ) { mat_inverse_matrix_d3( inv_lat, min_lat, 0 ); mat_multiply_matrix_d3( trans_mat, inv_lat, cell->lattice ); smallest_cell = cel_alloc_cell( cell->size ); mat_copy_matrix_d3( smallest_cell->lattice, min_lat ); for ( i = 0; i < cell->size; i++ ) { smallest_cell->types[i] = cell->types[i]; mat_multiply_matrix_vector_d3( smallest_cell->position[i], trans_mat, cell->position[i] ); for ( j = 0; j < 3; j++ ) { cell->position[i][j] -= mat_Nint( cell->position[i][j] ); } } } else { smallest_cell = cel_alloc_cell( -1 ); } return smallest_cell; }
static Cell * get_conventional_primitive(SPGCONST Spacegroup * spacegroup, SPGCONST Cell * primitive) { int i, j; double inv_brv[3][3], trans_mat[3][3]; Cell * conv_prim; conv_prim = cel_alloc_cell(primitive->size); mat_inverse_matrix_d3(inv_brv, spacegroup->bravais_lattice, 0); mat_multiply_matrix_d3(trans_mat, inv_brv, primitive->lattice); for (i = 0; i < primitive->size; i++) { conv_prim->types[i] = primitive->types[i]; mat_multiply_matrix_vector_d3(conv_prim->position[i], trans_mat, primitive->position[i]); for (j = 0; j < 3; j++) { conv_prim->position[i][j] -= spacegroup->origin_shift[j]; conv_prim->position[i][j] -= mat_Nint(conv_prim->position[i][j]); } } return conv_prim; }
static VecDBL * get_positions_primitive( SPGCONST Cell * cell, SPGCONST double prim_lat[3][3] ) { int i, j; double tmp_matrix[3][3], axis_inv[3][3]; VecDBL * position; position = mat_alloc_VecDBL( cell->size ); mat_inverse_matrix_d3(tmp_matrix, prim_lat, 0); mat_multiply_matrix_d3(axis_inv, tmp_matrix, cell->lattice); /* Send atoms into the primitive cell */ debug_print("Positions in new axes reduced to primitive cell\n"); for (i = 0; i < cell->size; i++) { mat_multiply_matrix_vector_d3( position->vec[i], axis_inv, cell->position[i] ); for (j = 0; j < 3; j++) { position->vec[i][j] -= mat_Nint( position->vec[i][j] ); } debug_print("%d: %f %f %f\n", i + 1, position->vec[i][0], position->vec[i][1], position->vec[i][2]); } return position; }
/* Return NULL if failed */ static VecDBL * get_positions_primitive(SPGCONST Cell * cell, SPGCONST double prim_lat[3][3]) { int i, j; double tmp_matrix[3][3], axis_inv[3][3]; VecDBL * position; position = NULL; if ((position = mat_alloc_VecDBL(cell->size)) == NULL) { return NULL; } mat_inverse_matrix_d3(tmp_matrix, prim_lat, 0); mat_multiply_matrix_d3(axis_inv, tmp_matrix, cell->lattice); /* Send atoms into the primitive cell */ for (i = 0; i < cell->size; i++) { mat_multiply_matrix_vector_d3(position->vec[i], axis_inv, cell->position[i]); for (j = 0; j < 3; j++) { position->vec[i][j] -= mat_Nint(position->vec[i][j]); } } return position; }
/* Return NULL if failed */ static VecDBL * translate_atoms_in_trimmed_lattice(const Cell * cell, SPGCONST double trimmed_lattice[3][3]) { int i, j; double tmp_matrix[3][3], axis_inv[3][3]; VecDBL * position; position = NULL; if ((position = mat_alloc_VecDBL(cell->size)) == NULL) { return NULL; } mat_inverse_matrix_d3(tmp_matrix, trimmed_lattice, 0); mat_multiply_matrix_d3(axis_inv, tmp_matrix, cell->lattice); /* Send atoms into the trimmed cell */ for (i = 0; i < cell->size; i++) { mat_multiply_matrix_vector_d3(position->vec[i], axis_inv, cell->position[i]); for (j = 0; j < 3; j++) { position->vec[i][j] = mat_Dmod1(position->vec[i][j]); } } return position; }
static Symmetry * recover_symmetry_in_original_cell(const int frame[3], SPGCONST Symmetry *prim_sym, SPGCONST int t_mat[3][3], SPGCONST double lattice[3][3], const int multiplicity, const double symprec) { Symmetry *symmetry, *t_sym; double inv_tmat[3][3], tmp_mat[3][3]; VecDBL *pure_trans, *lattice_trans; symmetry = NULL; t_sym = NULL; pure_trans = NULL; lattice_trans = NULL; mat_cast_matrix_3i_to_3d(tmp_mat, t_mat); mat_inverse_matrix_d3(inv_tmat, tmp_mat, 0); if ((lattice_trans = get_lattice_translations(frame, inv_tmat)) == NULL) { return NULL; } if ((pure_trans = remove_overlapping_lattice_points(lattice, lattice_trans, symprec)) == NULL) { mat_free_VecDBL(lattice_trans); lattice_trans = NULL; return NULL; } if ((t_sym = get_symmetry_in_original_cell(t_mat, inv_tmat, lattice, prim_sym, symprec)) == NULL) { mat_free_VecDBL(pure_trans); pure_trans = NULL; mat_free_VecDBL(lattice_trans); lattice_trans = NULL; return NULL; } if (pure_trans->size == multiplicity) { symmetry = copy_symmetry_upon_lattice_points(pure_trans, t_sym); } mat_free_VecDBL(lattice_trans); lattice_trans = NULL; mat_free_VecDBL(pure_trans); pure_trans = NULL; sym_free_symmetry(t_sym); t_sym = NULL; return symmetry; }
static void set_dataset(SpglibDataset * dataset, SPGCONST Cell * cell, SPGCONST Cell * primitive, SPGCONST Spacegroup * spacegroup, const int * mapping_table, const double tolerance) { int i; double inv_mat[3][3]; Cell *bravais; Symmetry *symmetry; /* Spacegroup type, transformation matrix, origin shift */ dataset->n_atoms = cell->size; dataset->spacegroup_number = spacegroup->number; dataset->hall_number = spacegroup->hall_number; strcpy(dataset->international_symbol, spacegroup->international_short); strcpy(dataset->hall_symbol, spacegroup->hall_symbol); strcpy(dataset->setting, spacegroup->setting); mat_inverse_matrix_d3(inv_mat, cell->lattice, tolerance); mat_multiply_matrix_d3(dataset->transformation_matrix, inv_mat, spacegroup->bravais_lattice); mat_copy_vector_d3(dataset->origin_shift, spacegroup->origin_shift); /* Symmetry operations */ symmetry = ref_get_refined_symmetry_operations(cell, primitive, spacegroup, tolerance); dataset->rotations = (int (*)[3][3])malloc(sizeof(int[3][3]) * symmetry->size); dataset->translations = (double (*)[3])malloc(sizeof(double[3]) * symmetry->size); dataset->n_operations = symmetry->size; for (i = 0; i < symmetry->size; i++) { mat_copy_matrix_i3(dataset->rotations[i], symmetry->rot[i]); mat_copy_vector_d3(dataset->translations[i], symmetry->trans[i]); } /* Wyckoff positions */ dataset->wyckoffs = (int*) malloc(sizeof(int) * cell->size); dataset->equivalent_atoms = (int*) malloc(sizeof(int) * cell->size); bravais = ref_get_Wyckoff_positions(dataset->wyckoffs, dataset->equivalent_atoms, primitive, cell, spacegroup, symmetry, mapping_table, tolerance); cel_free_cell(bravais); sym_free_symmetry(symmetry); }
/* m = b^-1 a b */ int mat_get_similar_matrix_d3(double m[3][3], const double a[3][3], const double b[3][3], const double precision) { double c[3][3]; if (!mat_inverse_matrix_d3(c, b, precision)) { fprintf(stderr, "spglib: No similar matrix due to 0 determinant.\n"); return 0; } mat_multiply_matrix_d3(m, a, b); mat_multiply_matrix_d3(m, c, m); return 1; }
/* Return NULL if failed */ Cell * spa_transform_to_primitive(SPGCONST Cell * cell, SPGCONST double trans_mat[3][3], const Centering centering, const double symprec) { int * mapping_table; double tmat[3][3], tmat_inv[3][3], prim_lat[3][3]; Cell * primitive; mapping_table = NULL; primitive = NULL; mat_inverse_matrix_d3(tmat_inv, trans_mat, 0); switch (centering) { case PRIMITIVE: mat_copy_matrix_d3(tmat, tmat_inv); break; case A_FACE: mat_multiply_matrix_d3(tmat, tmat_inv, A_mat); break; case C_FACE: mat_multiply_matrix_d3(tmat, tmat_inv, C_mat); break; case FACE: mat_multiply_matrix_d3(tmat, tmat_inv, F_mat); break; case BODY: mat_multiply_matrix_d3(tmat, tmat_inv, I_mat); break; case R_CENTER: mat_multiply_matrix_d3(tmat, tmat_inv, R_mat); break; default: goto err; } if ((mapping_table = (int*) malloc(sizeof(int) * cell->size)) == NULL) { warning_print("spglib: Memory could not be allocated "); goto err; } mat_multiply_matrix_d3(prim_lat, cell->lattice, tmat); primitive = cel_trim_cell(mapping_table, prim_lat, cell, symprec); free(mapping_table); mapping_table = NULL; return primitive; err: return NULL; }
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; }
/* m = b^-1 a b */ int mat_get_similar_matrix_d3(double m[3][3], SPGCONST double a[3][3], SPGCONST double b[3][3], const double precision) { double c[3][3]; if (!mat_inverse_matrix_d3(c, b, precision)) { warning_print("spglib: No similar matrix due to 0 determinant.\n"); debug_print("No similar matrix due to 0 determinant.\n"); return 0; } mat_multiply_matrix_d3(m, a, b); mat_multiply_matrix_d3(m, c, m); return 1; }
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; }
/* Return 0 if failed */ static int change_basis_monocli(int int_transform_mat[3][3], SPGCONST double conv_lattice[3][3], SPGCONST double primitive_lattice[3][3], const double symprec) { double smallest_lattice[3][3], inv_lattice[3][3], transform_mat[3][3]; if (! del_delaunay_reduce_2D(smallest_lattice, conv_lattice, 1, /* unique axis of b */ symprec)) { return 0; } mat_inverse_matrix_d3(inv_lattice, primitive_lattice, 0); mat_multiply_matrix_d3(transform_mat, inv_lattice, smallest_lattice); mat_cast_matrix_3d_to_3i(int_transform_mat, transform_mat); return 1; }
/* Return NULL if failed */ static Cell * get_cell_with_smallest_lattice(SPGCONST Cell * cell, const double symprec) { int i, j; double min_lat[3][3], trans_mat[3][3], inv_lat[3][3]; Cell * smallest_cell; debug_print("get_cell_with_smallest_lattice:\n"); smallest_cell = NULL; if (!lat_smallest_lattice_vector(min_lat, cell->lattice, symprec)) { goto err; } mat_inverse_matrix_d3(inv_lat, min_lat, 0); mat_multiply_matrix_d3(trans_mat, inv_lat, cell->lattice); if ((smallest_cell = cel_alloc_cell(cell->size)) == NULL) { goto err; } mat_copy_matrix_d3(smallest_cell->lattice, min_lat); for (i = 0; i < cell->size; i++) { smallest_cell->types[i] = cell->types[i]; mat_multiply_matrix_vector_d3(smallest_cell->position[i], trans_mat, cell->position[i]); for (j = 0; j < 3; j++) { cell->position[i][j] = mat_Dmod1(cell->position[i][j]); } } return smallest_cell; err: return NULL; }
/* Return 0 if failed */ static int change_basis_tricli(int int_transform_mat[3][3], SPGCONST double conv_lattice[3][3], SPGCONST double primitive_lattice[3][3], const double symprec) { int i, j; double niggli_cell[9]; double smallest_lattice[3][3], inv_lattice[3][3], transform_mat[3][3]; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { niggli_cell[i * 3 + j] = conv_lattice[i][j]; } } if (! niggli_reduce(niggli_cell, symprec * symprec)) { return 0; } for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { smallest_lattice[i][j] = niggli_cell[i * 3 + j]; } } if (mat_get_determinant_d3(smallest_lattice) < 0) { for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { smallest_lattice[i][j] = -smallest_lattice[i][j]; } } } mat_inverse_matrix_d3(inv_lattice, primitive_lattice, 0); mat_multiply_matrix_d3(transform_mat, inv_lattice, smallest_lattice); mat_cast_matrix_3d_to_3i(int_transform_mat, transform_mat); return 1; }
static Symmetry * get_conventional_symmetry(SPGCONST double transform_mat[3][3], const Centering centering, const Symmetry *primitive_sym) { int i, j, k, multi, size; double tmp_trans; double tmp_matrix_d3[3][3], shift[4][3]; double symmetry_rot_d3[3][3], primitive_sym_rot_d3[3][3]; Symmetry *symmetry; size = primitive_sym->size; if (centering == FACE) { symmetry = sym_alloc_symmetry(size * 4); } else { if (centering) { symmetry = sym_alloc_symmetry(size * 2); } else { symmetry = sym_alloc_symmetry(size); } } for (i = 0; i < size; i++) { mat_cast_matrix_3i_to_3d(primitive_sym_rot_d3, primitive_sym->rot[i]); /* C*S*C^-1: recover conventional cell symmetry operation */ mat_get_similar_matrix_d3(symmetry_rot_d3, primitive_sym_rot_d3, transform_mat, 0); mat_cast_matrix_3d_to_3i(symmetry->rot[i], symmetry_rot_d3); /* translation in conventional cell: C = B^-1*P */ mat_inverse_matrix_d3(tmp_matrix_d3, transform_mat, 0); mat_multiply_matrix_vector_d3(symmetry->trans[i], tmp_matrix_d3, primitive_sym->trans[i]); } multi = 1; if (centering) { if (! (centering == FACE)) { for (i = 0; i < 3; i++) { shift[0][i] = 0.5; } if (centering == A_FACE) { shift[0][0] = 0; } if (centering == B_FACE) { shift[0][1] = 0; } if (centering == C_FACE) { shift[0][2] = 0; } multi = 2; } if (centering == FACE) { shift[0][0] = 0; shift[0][1] = 0.5; shift[0][2] = 0.5; shift[1][0] = 0.5; shift[1][1] = 0; shift[1][2] = 0.5; shift[2][0] = 0.5; shift[2][1] = 0.5; shift[2][2] = 0; multi = 4; } for (i = 0; i < multi - 1; i++) { for (j = 0; j < size; j++) { mat_copy_matrix_i3(symmetry->rot[(i+1) * size + j], symmetry->rot[j]); for (k = 0; k < 3; k++) { tmp_trans = symmetry->trans[j][k] + shift[i][k]; symmetry->trans[(i+1) * size + j][k] = tmp_trans; } } } } /* Reduce translations into -0 < trans < 1.0 */ for (i = 0; i < multi; i++) { for (j = 0; j < size; j++) { for (k = 0; k < 3; k++) { tmp_trans = symmetry->trans[i * size + j][k]; tmp_trans -= mat_Nint(tmp_trans); if (tmp_trans < 0) { tmp_trans += 1.0; } symmetry->trans[i * size + j][k] = tmp_trans; } } } return symmetry; }
/* (http://phonopy.sf.net/) */ static void test_tetrahedron_method(void) { printf("*** Example of tetrahedron method of NaCl to calculate DOS ***:\n"); printf("Read data from frequency.dat and write DOS to dos.dat.\n"); int i, j, k, l, q, r; /* NaCl 20x20x20 mesh */ double lattice[3][3] = { {0.000000000000000, 2.845150738087836, 2.845150738087836}, {2.845150738087836, 0.000000000000000, 2.845150738087836}, {2.845150738087836, 2.845150738087836, 0.000000000000000} }; double position[][3] = {{0, 0, 0}, {0.5, 0.5, 0.5}}; int types[] = {1, 2}; int num_atom = 2; int m = 20; int mesh[] = {m, m, m}; int num_gp = mesh[0] * mesh[1] * mesh[2]; int is_shift[] = {0, 0, 0}; int grid_address[num_gp][3]; int grid_mapping_table[num_gp]; int weights[num_gp]; int num_ir = spg_get_ir_reciprocal_mesh(grid_address, grid_mapping_table, mesh, is_shift, 1, lattice, position, types, num_atom, 1e-5); int ir_gp[num_ir]; int ir_weights[num_ir]; int gp_ir_index[num_gp]; int relative_grid_address[24][4][3]; double rec_lat[3][3]; FILE *fp; char * line = NULL; size_t len = 0; ssize_t read; double frequency[num_ir * num_atom * 3]; double max_f, min_f; double t_omegas[24][4]; int g_addr[3]; int gp; int num_freqs = 201; double dos[num_freqs]; double integral_dos[num_freqs]; double omegas[num_freqs]; double iw; for (i = 0; i < num_gp; i++) { weights[i] = 0; } for (i = 0; i < num_gp; i++) { weights[grid_mapping_table[i]]++; } j = 0; for (i = 0; i < num_gp; i++) { if (weights[i] != 0) { ir_gp[j] = i; ir_weights[j] = weights[i]; gp_ir_index[i] = j; j++; } else { gp_ir_index[i] = gp_ir_index[grid_mapping_table[i]]; } } printf("Number of irreducible k-points: %d\n", num_ir); mat_inverse_matrix_d3(rec_lat, lattice, 1e-5); thm_get_relative_grid_address(relative_grid_address, rec_lat); /* for (i = 0; i < 24; i++) { */ /* for (j = 0; j < 4; j++) { */ /* printf("[%2d %2d %2d] ", */ /* relative_grid_address[i][j][0], */ /* relative_grid_address[i][j][1], */ /* relative_grid_address[i][j][2]); */ /* } */ /* printf("\n"); */ /* } */ fp = fopen("frequency.dat", "r"); for (i = 0; i < num_ir * num_atom * 3; i++) { read = getline(&line, &len, fp); if (read == -1) { break; } frequency[i] = strtod(line, NULL); } fclose(fp); max_f = frequency[0]; min_f = frequency[0]; for (i = 0; i < num_ir * num_atom * 3; i++) { if (max_f < frequency[i]) { max_f = frequency[i]; } if (min_f > frequency[i]) { min_f = frequency[i]; } } printf("Number of frequencies: %d\n", i); #pragma omp parallel for private(j, k, l, q, r, g_addr, gp, t_omegas, iw) for (i = 0; i < num_freqs; i++) { dos[i] = 0; integral_dos[i] = 0; omegas[i] = min_f + (max_f - min_f) / (num_freqs - 1) * i; for (j = 0; j < num_ir; j++) { for (k = 0; k < num_atom * 3; k++) { for (l = 0; l < 24; l++) { for (q = 0; q < 4; q++) { for (r = 0; r < 3; r++) { g_addr[r] = grid_address[ir_gp[j]][r] + relative_grid_address[l][q][r]; } gp = spg_get_grid_point_from_address(g_addr, mesh); t_omegas[l][q] = frequency[gp_ir_index[gp] * num_atom * 3 + k]; } } iw = thm_get_integration_weight(omegas[i], t_omegas, 'J'); dos[i] += iw * ir_weights[j]; iw = thm_get_integration_weight(omegas[i], t_omegas, 'I'); integral_dos[i] += iw * ir_weights[j]; } } } fp = fopen("dos.dat", "w"); for (i = 0; i < num_freqs; i++) { fprintf(fp, "%f %f\n", omegas[i], dos[i] / num_gp); } fprintf(fp, "\n\n"); for (i = 0; i < num_freqs; i++) { fprintf(fp, "%f %f\n", omegas[i], integral_dos[i] / num_gp); } fclose(fp); }
static Symmetry * reduce_symmetry_in_frame(const int frame[3], SPGCONST Symmetry *prim_sym, SPGCONST int t_mat[3][3], SPGCONST double lattice[3][3], const int multiplicity, const double symprec) { int i, j, k, l, num_trans, size_sym_orig; Symmetry *symmetry, *t_sym; double inv_tmat[3][3], tmp_mat[3][3], tmp_rot_d[3][3], tmp_lat_d[3][3], tmp_lat_i[3][3]; int tmp_rot_i[3][3]; VecDBL *pure_trans, *lattice_trans; mat_cast_matrix_3i_to_3d(tmp_mat, t_mat); mat_inverse_matrix_d3(inv_tmat, tmp_mat, symprec); /* transformed lattice points */ lattice_trans = mat_alloc_VecDBL(frame[0]*frame[1]*frame[2]); num_trans = 0; for (i = 0; i < frame[0]; i++) { for (j = 0; j < frame[1]; j++) { for (k = 0; k < frame[2]; k++) { lattice_trans->vec[num_trans][0] = i; lattice_trans->vec[num_trans][1] = j; lattice_trans->vec[num_trans][2] = k; mat_multiply_matrix_vector_d3(lattice_trans->vec[num_trans], inv_tmat, lattice_trans->vec[num_trans]); for (l = 0; l < 3; l++) { /* t' = T^-1*t */ lattice_trans->vec[num_trans][l] = \ mat_Dmod1(lattice_trans->vec[num_trans][l]); } num_trans++; } } } /* transformed symmetry operations of primitive cell */ t_sym = sym_alloc_symmetry(prim_sym->size); size_sym_orig = 0; for (i = 0; i < prim_sym->size; i++) { /* R' = T^-1*R*T */ mat_multiply_matrix_di3(tmp_mat, inv_tmat, prim_sym->rot[i]); mat_multiply_matrix_di3(tmp_rot_d, tmp_mat, t_mat); mat_cast_matrix_3d_to_3i(tmp_rot_i, tmp_rot_d); mat_multiply_matrix_di3(tmp_lat_i, lattice, tmp_rot_i); mat_multiply_matrix_d3(tmp_lat_d, lattice, tmp_rot_d); if (mat_check_identity_matrix_d3(tmp_lat_i, tmp_lat_d, symprec)) { mat_copy_matrix_i3(t_sym->rot[size_sym_orig], tmp_rot_i); /* t' = T^-1*t */ mat_multiply_matrix_vector_d3(t_sym->trans[size_sym_orig], inv_tmat, prim_sym->trans[i]); size_sym_orig++; } } /* reduce lattice points */ pure_trans = reduce_lattice_points(lattice, lattice_trans, symprec); if (! (pure_trans->size == multiplicity)) { symmetry = sym_alloc_symmetry(0); goto ret; } /* copy symmetry operations upon lattice points */ symmetry = sym_alloc_symmetry(pure_trans->size * size_sym_orig); for (i = 0; i < pure_trans->size; i++) { for (j = 0; j < size_sym_orig; j++) { mat_copy_matrix_i3(symmetry->rot[size_sym_orig * i + j], t_sym->rot[j]); mat_copy_vector_d3(symmetry->trans[size_sym_orig * i + j], t_sym->trans[j]); for (k = 0; k < 3; k++) { symmetry->trans[size_sym_orig * i + j][k] += pure_trans->vec[i][k]; symmetry->trans[size_sym_orig * i + j][k] = \ mat_Dmod1(symmetry->trans[size_sym_orig * i + j][k]); } } } ret: mat_free_VecDBL(lattice_trans); mat_free_VecDBL(pure_trans); sym_free_symmetry(t_sym); return symmetry; }
SpglibDataset * spg_get_dataset( SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const double symprec ) { int i, j; int *mapping_table, *wyckoffs, *equiv_atoms, *equiv_atoms_prim; Spacegroup spacegroup; SpglibDataset *dataset; Cell *cell, *primitive; double inv_mat[3][3]; Symmetry *symmetry; VecDBL *pure_trans; dataset = (SpglibDataset*) malloc( sizeof( SpglibDataset ) ); cell = cel_alloc_cell( num_atom ); cel_set_cell( cell, lattice, position, types ); pure_trans = sym_get_pure_translation( cell, symprec ); mapping_table = (int*) malloc( sizeof(int) * cell->size ); primitive = prm_get_primitive( mapping_table, cell, pure_trans, symprec ); mat_free_VecDBL( pure_trans ); spacegroup = spa_get_spacegroup_with_primitive( primitive, symprec ); /* Spacegroup type, transformation matrix, origin shift */ if ( spacegroup.number > 0 ) { dataset->spacegroup_number = spacegroup.number; strcpy( dataset->international_symbol, spacegroup.international_short); strcpy( dataset->hall_symbol, spacegroup.hall_symbol); mat_inverse_matrix_d3( inv_mat, lattice, symprec ); mat_multiply_matrix_d3( dataset->transformation_matrix, inv_mat, spacegroup.bravais_lattice ); mat_copy_vector_d3( dataset->origin_shift, spacegroup.origin_shift ); } /* Wyckoff positions */ wyckoffs = (int*) malloc( sizeof(int) * primitive->size ); equiv_atoms_prim = (int*) malloc( sizeof(int) * primitive->size ); for ( i = 0; i < primitive->size; i++ ) { wyckoffs[i] = -1; equiv_atoms_prim[i] = -1; } ref_get_Wyckoff_positions( wyckoffs, equiv_atoms_prim, primitive, &spacegroup, symprec ); dataset->n_atoms = cell->size; dataset->wyckoffs = (int*) malloc( sizeof(int) * cell->size ); for ( i = 0; i < cell->size; i++ ) { dataset->wyckoffs[i] = wyckoffs[ mapping_table[i] ]; } free( wyckoffs ); wyckoffs = NULL; dataset->equivalent_atoms = (int*) malloc( sizeof(int) * cell->size ); equiv_atoms = (int*) malloc( sizeof(int) * primitive->size ); for ( i = 0; i < primitive->size; i++ ) { for ( j = 0; j < cell->size; j++ ) { if ( mapping_table[j] == equiv_atoms_prim[i] ) { equiv_atoms[i] = j; break; } } } for ( i = 0; i < cell->size; i++ ) { dataset->equivalent_atoms[i] = equiv_atoms[ mapping_table[i] ]; } free( equiv_atoms ); equiv_atoms = NULL; free( equiv_atoms_prim ); equiv_atoms_prim = NULL; free( mapping_table ); mapping_table = NULL; /* Symmetry operations */ symmetry = ref_get_refined_symmetry_operations( cell, primitive->lattice, &spacegroup, symprec ); cel_free_cell( cell ); cel_free_cell( primitive ); dataset->rotations = (int (*)[3][3]) malloc(sizeof(int[3][3]) * symmetry->size ); dataset->translations = (double (*)[3]) malloc(sizeof(double[3]) * symmetry->size ); dataset->n_operations = symmetry->size; for ( i = 0; i < symmetry->size; i++ ) { mat_copy_matrix_i3( dataset->rotations[i], symmetry->rot[i] ); mat_copy_vector_d3( dataset->translations[i], symmetry->trans[i] ); } sym_free_symmetry( symmetry ); return dataset; }
/* Return NULL if failed */ static Symmetry * get_conventional_symmetry(SPGCONST double transform_mat[3][3], const Centering centering, const Symmetry *primitive_sym) { int i, j, k, multi, size; double inv_tmat[3][3], shift[4][3]; double symmetry_rot_d3[3][3], primitive_sym_rot_d3[3][3]; Symmetry *symmetry; symmetry = NULL; size = primitive_sym->size; switch (centering) { case FACE: if ((symmetry = sym_alloc_symmetry(size * 4)) == NULL) { return NULL; } break; case R_CENTER: if ((symmetry = sym_alloc_symmetry(size * 3)) == NULL) { return NULL; } break; case BODY: case A_FACE: case B_FACE: case C_FACE: if ((symmetry = sym_alloc_symmetry(size * 2)) == NULL) { return NULL; } break; default: if ((symmetry = sym_alloc_symmetry(size)) == NULL) { return NULL; } break; } for (i = 0; i < size; i++) { mat_cast_matrix_3i_to_3d(primitive_sym_rot_d3, primitive_sym->rot[i]); /* C*S*C^-1: recover conventional cell symmetry operation */ mat_get_similar_matrix_d3(symmetry_rot_d3, primitive_sym_rot_d3, transform_mat, 0); mat_cast_matrix_3d_to_3i(symmetry->rot[i], symmetry_rot_d3); /* translation in conventional cell: C = B^-1*P */ mat_inverse_matrix_d3(inv_tmat, transform_mat, 0); mat_multiply_matrix_vector_d3(symmetry->trans[i], inv_tmat, primitive_sym->trans[i]); } multi = 1; if (centering != PRIMITIVE) { if (centering != FACE && centering != R_CENTER) { for (i = 0; i < 3; i++) { shift[0][i] = 0.5; } /* BASE */ if (centering == A_FACE) { shift[0][0] = 0; } if (centering == B_FACE) { shift[0][1] = 0; } if (centering == C_FACE) { shift[0][2] = 0; } multi = 2; } if (centering == R_CENTER) { shift[0][0] = 2. / 3; shift[0][1] = 1. / 3; shift[0][2] = 1. / 3; shift[1][0] = 1. / 3; shift[1][1] = 2. / 3; shift[1][2] = 2. / 3; multi = 3; } if (centering == FACE) { shift[0][0] = 0; shift[0][1] = 0.5; shift[0][2] = 0.5; shift[1][0] = 0.5; shift[1][1] = 0; shift[1][2] = 0.5; shift[2][0] = 0.5; shift[2][1] = 0.5; shift[2][2] = 0; multi = 4; } for (i = 0; i < multi - 1; i++) { for (j = 0; j < size; j++) { mat_copy_matrix_i3(symmetry->rot[(i+1) * size + j], symmetry->rot[j]); for (k = 0; k < 3; k++) { symmetry->trans[(i+1) * size + j][k] = symmetry->trans[j][k] + shift[i][k]; } } } } for (i = 0; i < multi; i++) { for (j = 0; j < size; j++) { for (k = 0; k < 3; k++) { symmetry->trans[i * size + j][k] = mat_Dmod1(symmetry->trans[i * size + j][k]); } } } return symmetry; }
static Symmetry * reduce_symmetry_in_frame( const int frame[3], SPGCONST Symmetry *prim_sym, SPGCONST int t_mat[3][3], SPGCONST double lattice[3][3], const double symprec ) { int i, j, k, l, n, num_op, is_found; Symmetry *symmetry, *t_sym; double inv_mat[3][3], tmp_mat[3][3]; VecDBL *t, *lattice_trans; mat_cast_matrix_3i_to_3d( tmp_mat, t_mat ); mat_inverse_matrix_d3( inv_mat, tmp_mat, symprec ); /* transformed lattice points */ lattice_trans = mat_alloc_VecDBL( frame[0]*frame[1]*frame[2] ); n = 0; for ( i = 0; i < frame[0]; i++ ) { for ( j = 0; j < frame[1]; j++ ) { for ( k = 0; k < frame[2]; k++ ) { lattice_trans->vec[n][0] = i; lattice_trans->vec[n][1] = j; lattice_trans->vec[n][2] = k; mat_multiply_matrix_vector_d3( lattice_trans->vec[n], inv_mat, lattice_trans->vec[n] ); for ( l = 0; l < 3; l++ ) { /* t' = T^-1*t */ lattice_trans->vec[n][l] = mat_Dmod1( lattice_trans->vec[n][l] ); } n++; } } } /* transformed symmetry operations of primitive cell */ t_sym = sym_alloc_symmetry( prim_sym->size ); for ( i = 0; i < prim_sym->size; i++ ) { /* R' = T^-1*R*T */ mat_multiply_matrix_di3( tmp_mat, inv_mat, prim_sym->rot[i] ); mat_multiply_matrix_di3( tmp_mat, tmp_mat, t_mat ); mat_cast_matrix_3d_to_3i( t_sym->rot[i], tmp_mat ); /* t' = T^-1*t */ mat_multiply_matrix_vector_d3( t_sym->trans[i], inv_mat, prim_sym->trans[ i ] ); } /* reduce lattice points */ num_op = 0; t = mat_alloc_VecDBL( lattice_trans->size ); for ( i = 0; i < lattice_trans->size; i++ ) { is_found = 0; for ( j = 0; j < num_op; j++ ) { if ( cel_is_overlap( lattice_trans->vec[i], t->vec[j], lattice, symprec ) ) { is_found = 1; break; } } if ( ! is_found ) { mat_copy_vector_d3( t->vec[num_op], lattice_trans->vec[i] ); num_op++; } } /* copy symmetry operations upon lattice points */ symmetry = sym_alloc_symmetry( num_op * t_sym->size ); for ( i = 0; i < num_op; i++ ) { for ( j = 0; j < t_sym->size; j++ ) { mat_copy_matrix_i3( symmetry->rot[ t_sym->size * i + j ], t_sym->rot[j] ); mat_copy_vector_d3( symmetry->trans[ t_sym->size * i + j ], t_sym->trans[j] ); for ( k = 0; k < 3; k++ ) { symmetry->trans[ t_sym->size * i + j ][k] += t->vec[i][k]; symmetry->trans[ t_sym->size * i + j ][k] = \ mat_Dmod1( symmetry->trans[ t_sym->size * i + j ][k] ); } } } mat_free_VecDBL( t ); sym_free_symmetry( t_sym ); 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; }
/* Return 0 if failed */ static int match_hall_symbol_db(double origin_shift[3], double lattice[3][3], const int hall_number, const int pointgroup_number, const Holohedry holohedry, const Centering centering, SPGCONST Symmetry *symmetry, const double symprec) { int is_found, num_hall_types; SpacegroupType spacegroup_type; Symmetry * changed_symmetry; double changed_lattice[3][3], inv_lattice[3][3], transform_mat[3][3]; changed_symmetry = NULL; spacegroup_type = spgdb_get_spacegroup_type(hall_number); num_hall_types = (spacegroup_to_hall_number[spacegroup_type.number] - spacegroup_to_hall_number[spacegroup_type.number - 1]); if (pointgroup_number != spacegroup_type.pointgroup_number) { goto err; } switch (holohedry) { case MONOCLI: if (match_hall_symbol_db_monocli(origin_shift, lattice, hall_number, num_hall_types, centering, symmetry, symprec)) {return 1;} break; case ORTHO: if (spacegroup_type.number == 48 || spacegroup_type.number == 50 || spacegroup_type.number == 59 || spacegroup_type.number == 68 || spacegroup_type.number == 70) { /* uncount origin shift */ num_hall_types /= 2; } if (num_hall_types == 1) { if (match_hall_symbol_db_ortho(origin_shift, lattice, hall_number, centering, symmetry, 6, symprec)) {return 1;} break; } if (num_hall_types == 2) { if (match_hall_symbol_db_ortho(origin_shift, lattice, hall_number, centering, symmetry, 3, symprec)) {return 1;} break; } if (num_hall_types == 3) { mat_copy_matrix_d3(changed_lattice, lattice); if (! match_hall_symbol_db_ortho (origin_shift, changed_lattice, spacegroup_to_hall_number[spacegroup_type.number - 1], centering, symmetry, 0, symprec)) {break;} mat_inverse_matrix_d3(inv_lattice, lattice, 0); mat_multiply_matrix_d3(transform_mat, inv_lattice, changed_lattice); if ((changed_symmetry = get_conventional_symmetry(transform_mat, PRIMITIVE, symmetry)) == NULL) { goto err; } is_found = match_hall_symbol_db_ortho(origin_shift, changed_lattice, hall_number, centering, changed_symmetry, 2, symprec); sym_free_symmetry(changed_symmetry); changed_symmetry = NULL; if (is_found) { mat_copy_matrix_d3(lattice, changed_lattice); return 1; } break; } if (num_hall_types == 6) { if (match_hall_symbol_db_ortho(origin_shift, lattice, hall_number, centering, symmetry, 1, symprec)) {return 1;} break; } break; case CUBIC: if (hal_match_hall_symbol_db(origin_shift, lattice, hall_number, centering, symmetry, symprec)) {return 1;} if (hall_number == 501) { /* Try another basis for No.205 */ mat_multiply_matrix_d3(changed_lattice, lattice, change_of_basis_501); if ((changed_symmetry = get_conventional_symmetry(change_of_basis_501, PRIMITIVE, symmetry)) == NULL) { goto err; } is_found = hal_match_hall_symbol_db(origin_shift, changed_lattice, hall_number, PRIMITIVE, changed_symmetry, symprec); sym_free_symmetry(changed_symmetry); changed_symmetry = NULL; if (is_found) { mat_copy_matrix_d3(lattice, changed_lattice); return 1; } } break; case TRIGO: if (centering == R_CENTER) { if (hall_number == 433 || hall_number == 436 || hall_number == 444 || hall_number == 450 || hall_number == 452 || hall_number == 458 || hall_number == 460) { mat_multiply_matrix_d3(changed_lattice, lattice, hR_to_hP); if ((changed_symmetry = get_conventional_symmetry(hR_to_hP, R_CENTER, symmetry)) == NULL) { goto err; } is_found = hal_match_hall_symbol_db(origin_shift, changed_lattice, hall_number, centering, changed_symmetry, symprec); sym_free_symmetry(changed_symmetry); changed_symmetry = NULL; if (is_found) { mat_copy_matrix_d3(lattice, changed_lattice); return 1; } } } /* Do not break for other trigonal cases */ default: /* HEXA, TETRA, TRICLI and rest of TRIGO */ if (hal_match_hall_symbol_db(origin_shift, lattice, hall_number, centering, symmetry, symprec)) { return 1; } break; } err: return 0; }
/* Return 0 if failed */ static int set_dataset(SpglibDataset * dataset, SPGCONST Cell * cell, SPGCONST Cell * primitive, SPGCONST Spacegroup * spacegroup, const int * mapping_table, const double tolerance) { int i; double inv_mat[3][3]; Cell *bravais; Symmetry *symmetry; bravais = NULL; symmetry = NULL; /* Spacegroup type, transformation matrix, origin shift */ dataset->n_atoms = cell->size; dataset->spacegroup_number = spacegroup->number; dataset->hall_number = spacegroup->hall_number; strcpy(dataset->international_symbol, spacegroup->international_short); strcpy(dataset->hall_symbol, spacegroup->hall_symbol); strcpy(dataset->setting, spacegroup->setting); mat_inverse_matrix_d3(inv_mat, cell->lattice, tolerance); mat_multiply_matrix_d3(dataset->transformation_matrix, inv_mat, spacegroup->bravais_lattice); mat_copy_vector_d3(dataset->origin_shift, spacegroup->origin_shift); /* Symmetry operations */ if ((symmetry = ref_get_refined_symmetry_operations(cell, primitive, spacegroup, tolerance)) == NULL) { return 0; } dataset->n_operations = symmetry->size; if ((dataset->rotations = (int (*)[3][3]) malloc(sizeof(int[3][3]) * dataset->n_operations)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } if ((dataset->translations = (double (*)[3]) malloc(sizeof(double[3]) * dataset->n_operations)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } for (i = 0; i < symmetry->size; i++) { mat_copy_matrix_i3(dataset->rotations[i], symmetry->rot[i]); mat_copy_vector_d3(dataset->translations[i], symmetry->trans[i]); } /* Wyckoff positions */ if ((dataset->wyckoffs = (int*) malloc(sizeof(int) * dataset->n_atoms)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } if ((dataset->equivalent_atoms = (int*) malloc(sizeof(int) * dataset->n_atoms)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } if ((bravais = ref_get_Wyckoff_positions(dataset->wyckoffs, dataset->equivalent_atoms, primitive, cell, spacegroup, symmetry, mapping_table, tolerance)) == NULL) { goto err; } dataset->n_brv_atoms = bravais->size; mat_copy_matrix_d3(dataset->brv_lattice, bravais->lattice); if ((dataset->brv_positions = (double (*)[3]) malloc(sizeof(double[3]) * dataset->n_brv_atoms)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } if ((dataset->brv_types = (int*) malloc(sizeof(int) * dataset->n_brv_atoms)) == NULL) { warning_print("spglib: Memory could not be allocated."); goto err; } for (i = 0; i < dataset->n_brv_atoms; i++) { mat_copy_vector_d3(dataset->brv_positions[i], bravais->position[i]); dataset->brv_types[i] = bravais->types[i]; } cel_free_cell(bravais); sym_free_symmetry(symmetry); return 1; err: if (dataset->brv_positions != NULL) { free(dataset->brv_positions); dataset->brv_positions = NULL; } if (bravais != NULL) { cel_free_cell(bravais); } if (dataset->equivalent_atoms != NULL) { free(dataset->equivalent_atoms); dataset->equivalent_atoms = NULL; } if (dataset->wyckoffs != NULL) { free(dataset->wyckoffs); dataset->wyckoffs = NULL; } if (dataset->translations != NULL) { free(dataset->translations); dataset->translations = NULL; } if (dataset->rotations != NULL) { free(dataset->rotations); dataset->rotations = NULL; } if (symmetry != NULL) { sym_free_symmetry(symmetry); } return 0; }