int kpt_get_stabilized_reciprocal_mesh(int grid_address[][3], int map[], const int mesh[3], const int is_shift[3], const int is_time_reversal, const MatINT * rotations, const int num_q, SPGCONST double qpoints[][3]) { int num_ir; MatINT *rot_reciprocal, *rot_reciprocal_q; double tolerance; rot_reciprocal = NULL; rot_reciprocal_q = NULL; rot_reciprocal = get_point_group_reciprocal(rotations, is_time_reversal); tolerance = 0.01 / (mesh[0] + mesh[1] + mesh[2]); rot_reciprocal_q = get_point_group_reciprocal_with_q(rot_reciprocal, tolerance, num_q, qpoints); num_ir = get_ir_reciprocal_mesh(grid_address, map, mesh, is_shift, rot_reciprocal_q); mat_free_MatINT(rot_reciprocal_q); rot_reciprocal_q = NULL; mat_free_MatINT(rot_reciprocal); rot_reciprocal = NULL; return num_ir; }
/*---------*/ static int get_ir_reciprocal_mesh(int grid_address[][3], int map[], const int mesh[3], const int is_shift[3], const int is_time_reversal, SPGCONST double lattice[3][3], SPGCONST double position[][3], const int types[], const int num_atom, const double symprec) { SpglibDataset *dataset; int num_ir, i; MatINT *rotations; dataset = get_dataset(lattice, position, types, num_atom, symprec); rotations = mat_alloc_MatINT(dataset->n_operations); for (i = 0; i < dataset->n_operations; i++) { mat_copy_matrix_i3(rotations->mat[i], dataset->rotations[i]); } num_ir = kpt_get_irreducible_reciprocal_mesh(grid_address, map, mesh, is_shift, is_time_reversal, rotations); mat_free_MatINT(rotations); spg_free_dataset(dataset); return num_ir; }
static int get_stabilized_reciprocal_mesh(int grid_address[][3], int map[], const int mesh[3], const int is_shift[3], const int is_time_reversal, const int num_rot, SPGCONST int rotations[][3][3], const int num_q, SPGCONST double qpoints[][3]) { MatINT *rot_real; int i, num_ir; rot_real = mat_alloc_MatINT(num_rot); for (i = 0; i < num_rot; i++) { mat_copy_matrix_i3(rot_real->mat[i], rotations[i]); } num_ir = kpt_get_stabilized_reciprocal_mesh(grid_address, map, mesh, is_shift, is_time_reversal, rot_real, num_q, qpoints); mat_free_MatINT(rot_real); return num_ir; }
int spg_get_triplets_reciprocal_mesh_at_q( int weights[], int grid_points[][3], int third_q[], const int grid_point, const int mesh[3], const int is_time_reversal, SPGCONST double lattice[3][3], const int num_rot, SPGCONST int rotations[][3][3], const double symprec ) { MatINT *rot_real; int i, num_ir; rot_real = mat_alloc_MatINT( num_rot ); for ( i = 0; i < num_rot; i++ ) { mat_copy_matrix_i3( rot_real->mat[i], rotations[i] ); } num_ir = kpt_get_ir_triplets_at_q( weights, grid_points, third_q, grid_point, mesh, is_time_reversal, lattice, rot_real, symprec ); mat_free_MatINT( rot_real ); return num_ir; }
/* Each value of 'map' correspnds to the index of grid_point. */ int kpt_get_irreducible_reciprocal_mesh(int grid_points[][3], int map[], const int mesh[3], const int is_shift[3], const int is_time_reversal, const Symmetry * symmetry) { int i; PointSymmetry point_symmetry; MatINT *rotations; rotations = mat_alloc_MatINT(symmetry->size); for (i = 0; i < symmetry->size; i++) { mat_copy_matrix_i3(rotations->mat[i], symmetry->rot[i]); } point_symmetry = get_point_group_reciprocal(rotations, is_time_reversal); mat_free_MatINT(rotations); #ifdef _OPENMP return get_ir_reciprocal_mesh_openmp(grid_points, map, mesh, is_shift, &point_symmetry); #else return get_ir_reciprocal_mesh(grid_points, map, mesh, is_shift, &point_symmetry); #endif }
static int get_triplets_reciprocal_mesh_at_q(int map_triplets[], int map_q[], int grid_address[][3], const int grid_point, const int mesh[3], const int is_time_reversal, const int num_rot, SPGCONST int rotations[][3][3]) { MatINT *rot_real; int i, num_ir; rot_real = mat_alloc_MatINT(num_rot); for (i = 0; i < num_rot; i++) { mat_copy_matrix_i3(rot_real->mat[i], rotations[i]); } num_ir = tpk_get_ir_triplets_at_q(map_triplets, map_q, grid_address, grid_point, mesh, is_time_reversal, rot_real); mat_free_MatINT(rot_real); return num_ir; }
int spg_get_BZ_grid_points_by_rotations(int rot_grid_points[], const int address_orig[3], const int num_rot, SPGCONST int rot_reciprocal[][3][3], const int mesh[3], const int is_shift[3], const int bz_map[]) { int i; MatINT *rot; rot = NULL; if ((rot = mat_alloc_MatINT(num_rot)) == NULL) { return 0; } for (i = 0; i < num_rot; i++) { mat_copy_matrix_i3(rot->mat[i], rot_reciprocal[i]); } kpt_get_BZ_grid_points_by_rotations(rot_grid_points, address_orig, rot, mesh, is_shift, bz_map); mat_free_MatINT(rot); return 1; }
/* Each value of 'map' correspnds to the index of grid_point. */ int kpt_get_irreducible_reciprocal_mesh(int grid_address[][3], int map[], const int mesh[3], const int is_shift[3], const int is_time_reversal, const MatINT *rotations) { int num_ir; MatINT *rot_reciprocal; rot_reciprocal = get_point_group_reciprocal(rotations, is_time_reversal); #ifdef _OPENMP num_ir = get_ir_reciprocal_mesh_openmp(grid_address, map, mesh, is_shift, rot_reciprocal); #else num_ir = get_ir_reciprocal_mesh(grid_address, map, mesh, is_shift, rot_reciprocal); #endif mat_free_MatINT(rot_reciprocal); return num_ir; }
static int extract_triplets_reciprocal_mesh_at_q(int triplets_at_q[][3], int weight_triplets_at_q[], const int fixed_grid_number, const int num_triplets, SPGCONST int triplets[][3], const int mesh[3], const int is_time_reversal, const int num_rot, SPGCONST int rotations[][3][3]) { MatINT *rot_real; int i, num_ir; rot_real = mat_alloc_MatINT(num_rot); for (i = 0; i < num_rot; i++) { mat_copy_matrix_i3(rot_real->mat[i], rotations[i]); } num_ir = kpt_extract_triplets_reciprocal_mesh_at_q(triplets_at_q, weight_triplets_at_q, fixed_grid_number, num_triplets, triplets, mesh, is_time_reversal, rot_real); mat_free_MatINT(rot_real); return num_ir; }
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 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 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; }
SpglibTriplets * spg_get_triplets_reciprocal_mesh( const int mesh[3], const int is_time_reversal, SPGCONST double lattice[3][3], const int num_rot, SPGCONST int rotations[][3][3], const double symprec ) { int i, j, num_grid; MatINT *rot_real; Triplets *tps; SpglibTriplets *spg_triplets; num_grid = mesh[0] * mesh[1] * mesh[2]; rot_real = mat_alloc_MatINT( num_rot ); for ( i = 0; i < num_rot; i++ ) { mat_copy_matrix_i3( rot_real->mat[i], rotations[i] ); } tps = kpt_get_triplets_reciprocal_mesh( mesh, is_time_reversal, lattice, rot_real, symprec ); mat_free_MatINT( rot_real ); spg_triplets = (SpglibTriplets*) malloc( sizeof( SpglibTriplets ) ); spg_triplets->size = tps->size; spg_triplets->triplets = (int (*)[3]) malloc( sizeof(int[3]) * tps->size ); spg_triplets->weights = (int*) malloc( sizeof(int) * tps->size ); spg_triplets->mesh_points = (int (*)[3]) malloc( sizeof(int[3]) * num_grid ); for ( i = 0; i < 3; i++ ) { spg_triplets->mesh[i] = tps->mesh[i]; } for ( i = 0; i < num_grid; i++ ) { for ( j = 0; j < 3; j++ ) { spg_triplets->mesh_points[i][j] = tps->mesh_points[i][j]; } } for ( i = 0; i < tps->size; i++ ) { for ( j = 0; j < 3; j++ ) { spg_triplets->triplets[i][j] = tps->triplets[i][j]; } spg_triplets->weights[i] = tps->weights[i]; } kpt_free_triplets( tps ); return spg_triplets; }
/* 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; }
void spg_get_grid_points_by_rotations(int rot_grid_points[], const int address_orig[3], const int num_rot, SPGCONST int rot_reciprocal[][3][3], const int mesh[3], const int is_shift[3]) { int i; MatINT *rot; rot = mat_alloc_MatINT(num_rot); for (i = 0; i < num_rot; i++) { mat_copy_matrix_i3(rot->mat[i], rot_reciprocal[i]); } kpt_get_grid_points_by_rotations(rot_grid_points, address_orig, rot, mesh, is_shift); mat_free_MatINT(rot); }
int kpt_get_ir_triplets_at_q(int map_triplets[], int map_q[], int grid_address[][3], const int grid_point, const int mesh[3], const int is_time_reversal, const MatINT * rotations) { int num_ir; MatINT *rot_reciprocal; rot_reciprocal = get_point_group_reciprocal(rotations, is_time_reversal); num_ir = get_ir_triplets_at_q(map_triplets, map_q, grid_address, grid_point, mesh, rot_reciprocal); mat_free_MatINT(rot_reciprocal); return num_ir; }
int kpt_get_irreducible_kpoints(int map[], SPGCONST double kpoints[][3], const int num_kpoint, const Symmetry * symmetry, const int is_time_reversal, const double symprec) { int i; PointSymmetry point_symmetry; MatINT *rotations; rotations = mat_alloc_MatINT(symmetry->size); for (i = 0; i < symmetry->size; i++) { mat_copy_matrix_i3(rotations->mat[i], symmetry->rot[i]); } point_symmetry = get_point_group_reciprocal(rotations, is_time_reversal); mat_free_MatINT(rotations); return get_ir_kpoints(map, kpoints, num_kpoint, &point_symmetry, symprec); }
Symmetry * sym_get_operation( SPGCONST Cell *cell, const double symprec ) { int i, j, num_sym; MatINT *rot; VecDBL *trans; Symmetry *symmetry; rot = mat_alloc_MatINT( cell->size * 48 ); trans = mat_alloc_VecDBL( cell->size * 48 ); num_sym = get_operation( rot->mat, trans->vec, cell, symprec ); #ifdef DEBUG debug_print("*** get_symmetry (found symmetry operations) *** \n"); debug_print("Lattice \n"); debug_print_matrix_d3(cell->lattice); for ( i = 0; i < num_sym; i++ ) { debug_print("--- %d ---\n", i + 1); debug_print_matrix_i3(rot->mat[i]); debug_print("%f %f %f\n", trans->vec[i][0], trans->vec[i][1], trans->vec[i][2]); } #endif symmetry = sym_alloc_symmetry( num_sym ); for ( i = 0; i < num_sym; i++ ) { mat_copy_matrix_i3(symmetry->rot[i], rot->mat[i]); for (j = 0; j < 3; j++) symmetry->trans[i][j] = trans->vec[i][j]; } mat_free_MatINT( rot ); mat_free_VecDBL( trans ); return symmetry; }
/* 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; }
static int get_ir_triplets_at_q(int map_triplets[], int map_q[], int grid_address[][3], const int grid_point, const int mesh[3], const MatINT * rot_reciprocal) { int i, j, num_grid, q_2, num_ir_q, num_ir_triplets, ir_grid_point; int mesh_double[3], is_shift[3]; int address_double0[3], address_double1[3], address_double2[3]; int *ir_grid_points, *third_q; double tolerance; double stabilizer_q[1][3]; MatINT *rot_reciprocal_q; tolerance = 0.01 / (mesh[0] + mesh[1] + mesh[2]); num_grid = mesh[0] * mesh[1] * mesh[2]; for (i = 0; i < 3; i++) { /* Only consider the gamma-point */ is_shift[i] = 0; mesh_double[i] = mesh[i] * 2; } /* Search irreducible q-points (map_q) with a stabilizer */ /* q */ grid_point_to_address_double(address_double0, grid_point, mesh, is_shift); for (i = 0; i < 3; i++) { stabilizer_q[0][i] = (double)address_double0[i] / mesh_double[i] - (address_double0[i] > mesh[i]); } rot_reciprocal_q = kpt_get_point_group_reciprocal_with_q(rot_reciprocal, tolerance, 1, stabilizer_q); num_ir_q = kpt_get_irreducible_reciprocal_mesh(grid_address, map_q, mesh, is_shift, rot_reciprocal_q); mat_free_MatINT(rot_reciprocal_q); third_q = (int*) malloc(sizeof(int) * num_ir_q); ir_grid_points = (int*) malloc(sizeof(int) * num_ir_q); num_ir_q = 0; for (i = 0; i < num_grid; i++) { if (map_q[i] == i) { ir_grid_points[num_ir_q] = i; num_ir_q++; } map_triplets[i] = -1; } #pragma omp parallel for private(j, address_double1, address_double2) for (i = 0; i < num_ir_q; i++) { grid_point_to_address_double(address_double1, ir_grid_points[i], mesh, is_shift); /* q' */ for (j = 0; j < 3; j++) { /* q'' */ address_double2[j] = - address_double0[j] - address_double1[j]; } third_q[i] = kgd_get_grid_point_double_mesh(address_double2, mesh); } num_ir_triplets = 0; for (i = 0; i < num_ir_q; i++) { ir_grid_point = ir_grid_points[i]; q_2 = third_q[i]; if (map_triplets[map_q[q_2]] > -1) { map_triplets[ir_grid_point] = map_q[q_2]; } else { map_triplets[ir_grid_point] = ir_grid_point; num_ir_triplets++; } } #pragma omp parallel for for (i = 0; i < num_grid; i++) { map_triplets[i] = map_triplets[map_q[i]]; } free(third_q); third_q = NULL; free(ir_grid_points); ir_grid_points = NULL; return num_ir_triplets; }
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; }
static int get_ir_reciprocal_mesh(int grid_address[][3], int map[], const int mesh[3], const int is_shift[3], const MatINT *rot_reciprocal) { /* In the following loop, mesh is doubled. */ /* Even and odd mesh numbers correspond to */ /* is_shift[i] are 0 or 1, respectively. */ /* is_shift = [0,0,0] gives Gamma center mesh. */ /* grid: reducible grid points */ /* map: the mapping from each point to ir-point. */ int i, j, k, l, grid_point, grid_point_rot, num_ir = 0; int address_double[3], address_rot[3], mesh_double[3]; for (i = 0; i < 3; i++) { mesh_double[i] = mesh[i] * 2; } /* "-1" means the element is not touched yet. */ for (i = 0; i < mesh[0] * mesh[1] * mesh[2]; i++) { map[i] = -1; } #ifndef GRID_ORDER_XYZ for (i = 0; i < mesh[2]; i++) { for (j = 0; j < mesh[1]; j++) { for (k = 0; k < mesh[0]; k++) { address_double[0] = k * 2 + is_shift[0]; address_double[1] = j * 2 + is_shift[1]; address_double[2] = i * 2 + is_shift[2]; #else for (i = 0; i < mesh[0]; i++) { for (j = 0; j < mesh[1]; j++) { for (k = 0; k < mesh[2]; k++) { address_double[0] = i * 2 + is_shift[0]; address_double[1] = j * 2 + is_shift[1]; address_double[2] = k * 2 + is_shift[2]; #endif grid_point = get_grid_point_double_mesh(address_double, mesh); get_grid_address(grid_address[grid_point], address_double, mesh); for (l = 0; l < rot_reciprocal->size; l++) { mat_multiply_matrix_vector_i3(address_rot, rot_reciprocal->mat[l], address_double); get_vector_modulo(address_rot, mesh_double); grid_point_rot = get_grid_point_double_mesh(address_rot, mesh); if (grid_point_rot > -1) { /* Invalid if even --> odd or odd --> even */ if (map[grid_point_rot] > -1) { map[grid_point] = map[grid_point_rot]; break; } } } if (map[grid_point] == -1) { map[grid_point] = grid_point; num_ir++; } } } } return num_ir; } static int get_ir_reciprocal_mesh_openmp(int grid_address[][3], int map[], const int mesh[3], const int is_shift[3], const MatINT * rot_reciprocal) { int i, j, k, l, grid_point, grid_point_rot, num_ir; int address_double[3], address_rot[3], mesh_double[3]; for (i = 0; i < 3; i++) { mesh_double[i] = mesh[i] * 2; } #ifndef GRID_ORDER_XYZ #pragma omp parallel for private(j, k, l, grid_point, grid_point_rot, address_double, address_rot) for (i = 0; i < mesh[2]; i++) { for (j = 0; j < mesh[1]; j++) { for (k = 0; k < mesh[0]; k++) { address_double[0] = k * 2 + is_shift[0]; address_double[1] = j * 2 + is_shift[1]; address_double[2] = i * 2 + is_shift[2]; #else #pragma omp parallel for private(j, k, l, grid_point, grid_point_rot, address_double, address_rot) for (i = 0; i < mesh[0]; i++) { for (j = 0; j < mesh[1]; j++) { for (k = 0; k < mesh[2]; k++) { address_double[0] = i * 2 + is_shift[0]; address_double[1] = j * 2 + is_shift[1]; address_double[2] = k * 2 + is_shift[2]; #endif grid_point = get_grid_point_double_mesh(address_double, mesh); map[grid_point] = grid_point; get_grid_address(grid_address[grid_point], address_double, mesh); for (l = 0; l < rot_reciprocal->size; l++) { mat_multiply_matrix_vector_i3(address_rot, rot_reciprocal->mat[l], address_double); get_vector_modulo(address_rot, mesh_double); grid_point_rot = get_grid_point_double_mesh(address_rot, mesh); if (grid_point_rot > -1) { /* Invalid if even --> odd or odd --> even */ if (grid_point_rot < map[grid_point]) { map[grid_point] = grid_point_rot; } } } } } } num_ir = 0; #pragma omp parallel for reduction(+:num_ir) for (i = 0; i < mesh[0] * mesh[1] * mesh[2]; i++) { if (map[i] == i) { num_ir++; } } return num_ir; } /* Relocate grid addresses to first Brillouin zone */ /* bz_grid_address[prod(mesh + 1)][3] */ /* bz_map[prod(mesh * 2)] */ static int relocate_BZ_grid_address(int bz_grid_address[][3], int bz_map[], SPGCONST int grid_address[][3], const int mesh[3], SPGCONST double rec_lattice[3][3], const int is_shift[3]) { double tolerance, min_distance; double q_vector[3], distance[NUM_DIM_SEARCH]; int bzmesh[3], bzmesh_double[3], bz_address_double[3]; int i, j, k, min_index, boundary_num_gp, total_num_gp, bzgp, gp; tolerance = get_tolerance_for_BZ_reduction(rec_lattice, mesh); for (i = 0; i < 3; i++) { bzmesh[i] = mesh[i] * 2; bzmesh_double[i] = bzmesh[i] * 2; } for (i = 0; i < bzmesh[0] * bzmesh[1] * bzmesh[2]; i++) { bz_map[i] = -1; } boundary_num_gp = 0; total_num_gp = mesh[0] * mesh[1] * mesh[2]; for (i = 0; i < total_num_gp; i++) { for (j = 0; j < NUM_DIM_SEARCH; j++) { for (k = 0; k < 3; k++) { q_vector[k] = ((grid_address[i][k] + search_space[j][k] * mesh[k]) * 2 + is_shift[k]) / ((double)mesh[k]) / 2; } mat_multiply_matrix_vector_d3(q_vector, rec_lattice, q_vector); distance[j] = mat_norm_squared_d3(q_vector); } min_distance = distance[0]; min_index = 0; for (j = 1; j < NUM_DIM_SEARCH; j++) { if (distance[j] < min_distance) { min_distance = distance[j]; min_index = j; } } for (j = 0; j < NUM_DIM_SEARCH; j++) { if (distance[j] < min_distance + tolerance) { if (j == min_index) { gp = i; } else { gp = boundary_num_gp + total_num_gp; } for (k = 0; k < 3; k++) { bz_grid_address[gp][k] = grid_address[i][k] + search_space[j][k] * mesh[k]; bz_address_double[k] = bz_grid_address[gp][k] * 2 + is_shift[k]; } get_vector_modulo(bz_address_double, bzmesh_double); bzgp = get_grid_point_double_mesh(bz_address_double, bzmesh); bz_map[bzgp] = gp; if (j != min_index) { boundary_num_gp++; } } } } return boundary_num_gp + total_num_gp; } static double get_tolerance_for_BZ_reduction(SPGCONST double rec_lattice[3][3], const int mesh[3]) { int i, j; double tolerance; double length[3]; for (i = 0; i < 3; i++) { length[i] = 0; for (j = 0; j < 3; j++) { length[i] += rec_lattice[j][i] * rec_lattice[j][i]; } length[i] /= mesh[i] * mesh[i]; } tolerance = length[0]; for (i = 1; i < 3; i++) { if (tolerance < length[i]) { tolerance = length[i]; } } tolerance *= 0.01; return tolerance; } static int get_ir_triplets_at_q(int map_triplets[], int map_q[], int grid_address[][3], const int grid_point, const int mesh[3], const MatINT * rot_reciprocal) { int i, j, num_grid, q_2, num_ir_q, num_ir_triplets, ir_grid_point; int mesh_double[3], is_shift[3]; int address_double0[3], address_double1[3], address_double2[3]; int *ir_grid_points, *third_q; double tolerance; double stabilizer_q[1][3]; MatINT *rot_reciprocal_q; tolerance = 0.01 / (mesh[0] + mesh[1] + mesh[2]); num_grid = mesh[0] * mesh[1] * mesh[2]; for (i = 0; i < 3; i++) { /* Only consider the gamma-point */ is_shift[i] = 0; mesh_double[i] = mesh[i] * 2; } /* Search irreducible q-points (map_q) with a stabilizer */ /* q */ grid_point_to_address_double(address_double0, grid_point, mesh, is_shift); for (i = 0; i < 3; i++) { stabilizer_q[0][i] = (double)address_double0[i] / mesh_double[i] - (address_double0[i] > mesh[i]); } rot_reciprocal_q = get_point_group_reciprocal_with_q(rot_reciprocal, tolerance, 1, stabilizer_q); #ifdef _OPENMP num_ir_q = get_ir_reciprocal_mesh_openmp(grid_address, map_q, mesh, is_shift, rot_reciprocal_q); #else num_ir_q = get_ir_reciprocal_mesh(grid_address, map_q, mesh, is_shift, rot_reciprocal_q); #endif mat_free_MatINT(rot_reciprocal_q); third_q = (int*) malloc(sizeof(int) * num_ir_q); ir_grid_points = (int*) malloc(sizeof(int) * num_ir_q); num_ir_q = 0; for (i = 0; i < num_grid; i++) { if (map_q[i] == i) { ir_grid_points[num_ir_q] = i; num_ir_q++; } map_triplets[i] = -1; } #pragma omp parallel for private(j, address_double1, address_double2) for (i = 0; i < num_ir_q; i++) { grid_point_to_address_double(address_double1, ir_grid_points[i], mesh, is_shift); /* q' */ for (j = 0; j < 3; j++) { /* q'' */ address_double2[j] = - address_double0[j] - address_double1[j]; } get_vector_modulo(address_double2, mesh_double); third_q[i] = get_grid_point_double_mesh(address_double2, mesh); } num_ir_triplets = 0; for (i = 0; i < num_ir_q; i++) { ir_grid_point = ir_grid_points[i]; q_2 = third_q[i]; if (map_triplets[map_q[q_2]] > -1) { map_triplets[ir_grid_point] = map_q[q_2]; } else { map_triplets[ir_grid_point] = ir_grid_point; num_ir_triplets++; } } #pragma omp parallel for for (i = 0; i < num_grid; i++) { map_triplets[i] = map_triplets[map_q[i]]; } free(third_q); third_q = NULL; free(ir_grid_points); ir_grid_points = NULL; return num_ir_triplets; } static int get_BZ_triplets_at_q(int triplets[][3], const int grid_point, SPGCONST int bz_grid_address[][3], const int bz_map[], const int map_triplets[], const int num_map_triplets, const int mesh[3]) { int i, j, k, num_ir; int bz_address[3][3], bz_address_double[3], bzmesh[3], bzmesh_double[3]; int *ir_grid_points; for (i = 0; i < 3; i++) { bzmesh[i] = mesh[i] * 2; bzmesh_double[i] = bzmesh[i] * 2; } num_ir = 0; ir_grid_points = (int*) malloc(sizeof(int) * num_map_triplets); for (i = 0; i < num_map_triplets; i++) { if (map_triplets[i] == i) { ir_grid_points[num_ir] = i; num_ir++; } } #pragma omp parallel for private(j, k, bz_address, bz_address_double) for (i = 0; i < num_ir; i++) { for (j = 0; j < 3; j++) { bz_address[0][j] = bz_grid_address[grid_point][j]; bz_address[1][j] = bz_grid_address[ir_grid_points[i]][j]; bz_address[2][j] = - bz_address[0][j] - bz_address[1][j]; } for (j = 2; j > -1; j--) { if (get_third_q_of_triplets_at_q(bz_address, j, bz_map, mesh, bzmesh, bzmesh_double) == 0) { break; } } for (j = 0; j < 3; j++) { for (k = 0; k < 3; k++) { bz_address_double[k] = bz_address[j][k] * 2; } get_vector_modulo(bz_address_double, bzmesh_double); triplets[i][j] = bz_map[get_grid_point_double_mesh(bz_address_double, bzmesh)]; } } free(ir_grid_points); return num_ir; } static int get_third_q_of_triplets_at_q(int bz_address[3][3], const int q_index, const int bz_map[], const int mesh[3], const int bzmesh[3], const int bzmesh_double[3]) { int i, j, smallest_g, smallest_index, sum_g, delta_g[3]; int bzgp[NUM_DIM_SEARCH], bz_address_double[3]; get_vector_modulo(bz_address[q_index], mesh); for (i = 0; i < 3; i++) { delta_g[i] = 0; for (j = 0; j < 3; j++) { delta_g[i] += bz_address[j][i]; } delta_g[i] /= mesh[i]; } for (i = 0; i < NUM_DIM_SEARCH; i++) { for (j = 0; j < 3; j++) { bz_address_double[j] = (bz_address[q_index][j] + search_space[i][j] * mesh[j]) * 2; } for (j = 0; j < 3; j++) { if (bz_address_double[j] < 0) { bz_address_double[j] += bzmesh_double[j]; } } get_vector_modulo(bz_address_double, bzmesh_double); bzgp[i] = bz_map[get_grid_point_double_mesh(bz_address_double, bzmesh)]; } for (i = 0; i < NUM_DIM_SEARCH; i++) { if (bzgp[i] != -1) { goto escape; } } warning_print("******* Warning *******\n"); warning_print(" No third-q was found.\n"); warning_print("******* Warning *******\n"); escape: smallest_g = 4; smallest_index = 0; for (i = 0; i < NUM_DIM_SEARCH; i++) { if (bzgp[i] > -1) { /* q'' is in BZ */ sum_g = (abs(delta_g[0] + search_space[i][0]) + abs(delta_g[1] + search_space[i][1]) + abs(delta_g[2] + search_space[i][2])); if (sum_g < smallest_g) { smallest_index = i; smallest_g = sum_g; } } } for (i = 0; i < 3; i++) { bz_address[q_index][i] += search_space[smallest_index][i] * mesh[i]; } return smallest_g; }