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]) { int i, j, smallest_g, smallest_index, sum_g, delta_g[3]; int bzgp[KPT_NUM_BZ_SEARCH_SPACE], bz_address_double[3]; modulo_i3(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 < KPT_NUM_BZ_SEARCH_SPACE; i++) { for (j = 0; j < 3; j++) { bz_address_double[j] = (bz_address[q_index][j] + kpt_bz_search_space[i][j] * mesh[j]) * 2; } bzgp[i] = bz_map[kgd_get_grid_point_double_mesh(bz_address_double, bzmesh)]; } for (i = 0; i < KPT_NUM_BZ_SEARCH_SPACE; i++) { if (bzgp[i] != -1) { goto escape; } } escape: smallest_g = 4; smallest_index = 0; for (i = 0; i < KPT_NUM_BZ_SEARCH_SPACE; i++) { if (bzgp[i] > -1) { /* q'' is in BZ */ sum_g = (abs(delta_g[0] + kpt_bz_search_space[i][0]) + abs(delta_g[1] + kpt_bz_search_space[i][1]) + abs(delta_g[2] + kpt_bz_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] += kpt_bz_search_space[smallest_index][i] * mesh[i]; } return smallest_g; }
static int get_ir_reciprocal_mesh_distortion(int grid_address[][3], int ir_mapping_table[], const int mesh[3], const int is_shift[3], const MatINT *rot_reciprocal) { int i, j, k, grid_point_rot, indivisible; int address_double[3], address_double_rot[3], divisor[3]; kgd_get_all_grid_addresses(grid_address, mesh); for (i = 0; i < 3; i++) { divisor[i] = mesh[(i + 1) % 3] * mesh[(i + 2) % 3]; } #pragma omp parallel for private(j, k, grid_point_rot, address_double, address_double_rot) for (i = 0; i < mesh[0] * mesh[1] * mesh[2]; i++) { kgd_get_grid_address_double_mesh(address_double, grid_address[i], mesh, is_shift); for (j = 0; j < 3; j++) { address_double[j] *= divisor[j]; } ir_mapping_table[i] = i; for (j = 0; j < rot_reciprocal->size; j++) { mat_multiply_matrix_vector_i3(address_double_rot, rot_reciprocal->mat[j], address_double); for (k = 0; k < 3; k++) { indivisible = address_double_rot[k] % divisor[k]; if (indivisible) {break;} address_double_rot[k] /= divisor[k]; if ((address_double_rot[k] % 2 != 0 && is_shift[k] == 0) || (address_double_rot[k] % 2 == 0 && is_shift[k] == 1)) { indivisible = 1; break; } } if (indivisible) {continue;} grid_point_rot = kgd_get_grid_point_double_mesh(address_double_rot, mesh); if (grid_point_rot < ir_mapping_table[i]) { #ifdef _OPENMP ir_mapping_table[i] = grid_point_rot; #else ir_mapping_table[i] = ir_mapping_table[grid_point_rot]; break; #endif } } } return get_num_ir(ir_mapping_table, mesh); }
static int get_BZ_triplets_at_q(int triplets[][3], const int grid_point, PHPYCONST 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]; int *ir_grid_points; for (i = 0; i < 3; i++) { bzmesh[i] = mesh[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) == 0) { break; } } for (j = 0; j < 3; j++) { for (k = 0; k < 3; k++) { bz_address_double[k] = bz_address[j][k] * 2; } triplets[i][j] = bz_map[kgd_get_grid_point_double_mesh(bz_address_double, bzmesh)]; } } free(ir_grid_points); return num_ir; }
/*---------*/ int spg_get_grid_point_from_address(const int grid_address[3], const int mesh[3]) { int address_double[3]; int is_shift[3]; is_shift[0] = 0; is_shift[1] = 0; is_shift[2] = 0; kgd_get_grid_address_double_mesh(address_double, grid_address, mesh, is_shift); return kgd_get_grid_point_double_mesh(address_double, mesh); }
static int get_ir_reciprocal_mesh_normal(int grid_address[][3], int ir_mapping_table[], 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 */ /* ir_mapping_table: the mapping from each point to ir-point. */ int i, j, grid_point_rot; int address_double[3], address_double_rot[3]; kgd_get_all_grid_addresses(grid_address, mesh); #pragma omp parallel for private(j, grid_point_rot, address_double, address_double_rot) for (i = 0; i < mesh[0] * mesh[1] * mesh[2]; i++) { kgd_get_grid_address_double_mesh(address_double, grid_address[i], mesh, is_shift); ir_mapping_table[i] = i; for (j = 0; j < rot_reciprocal->size; j++) { mat_multiply_matrix_vector_i3(address_double_rot, rot_reciprocal->mat[j], address_double); grid_point_rot = kgd_get_grid_point_double_mesh(address_double_rot, mesh); if (grid_point_rot < ir_mapping_table[i]) { #ifdef _OPENMP ir_mapping_table[i] = grid_point_rot; #else ir_mapping_table[i] = ir_mapping_table[grid_point_rot]; break; #endif } } } return get_num_ir(ir_mapping_table, mesh); }
void kpt_get_grid_points_by_rotations(int rot_grid_points[], const int address_orig[3], const MatINT * rot_reciprocal, const int mesh[3], const int is_shift[3]) { int i; int address_double_orig[3], address_double[3]; for (i = 0; i < 3; i++) { address_double_orig[i] = address_orig[i] * 2 + is_shift[i]; } for (i = 0; i < rot_reciprocal->size; i++) { mat_multiply_matrix_vector_i3(address_double, rot_reciprocal->mat[i], address_double_orig); rot_grid_points[i] = kgd_get_grid_point_double_mesh(address_double, mesh); } }
/* 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[KPT_NUM_BZ_SEARCH_SPACE]; int bzmesh[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; } 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]; /* Multithreading doesn't work for this loop since gp calculated */ /* with boundary_num_gp is unstable to store bz_grid_address. */ for (i = 0; i < total_num_gp; i++) { for (j = 0; j < KPT_NUM_BZ_SEARCH_SPACE; j++) { for (k = 0; k < 3; k++) { q_vector[k] = ((grid_address[i][k] + bz_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 < KPT_NUM_BZ_SEARCH_SPACE; j++) { if (distance[j] < min_distance) { min_distance = distance[j]; min_index = j; } } for (j = 0; j < KPT_NUM_BZ_SEARCH_SPACE; 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] + bz_search_space[j][k] * mesh[k]; bz_address_double[k] = bz_grid_address[gp][k] * 2 + is_shift[k]; } bzgp = kgd_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 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; }