double spg_get_tetrahedra_integration_weight(const double omega, SPGCONST double tetrahedra_omegas[24][4], const char function) { return thm_get_integration_weight(omega, tetrahedra_omegas, function); }
static PyObject * py_set_triplets_integration_weights(PyObject *self, PyObject *args) { PyArrayObject* iw_py; PyArrayObject* frequency_points_py; PyArrayObject* relative_grid_address_py; PyArrayObject* mesh_py; PyArrayObject* triplets_py; PyArrayObject* frequencies_py; PyArrayObject* bz_grid_address_py; PyArrayObject* bz_map_py; if (!PyArg_ParseTuple(args, "OOOOOOOO", &iw_py, &frequency_points_py, &relative_grid_address_py, &mesh_py, &triplets_py, &frequencies_py, &bz_grid_address_py, &bz_map_py)) { return NULL; } double *iw = (double*)iw_py->data; const double *frequency_points = (double*)frequency_points_py->data; const int num_band0 = frequency_points_py->dimensions[0]; SPGCONST int (*relative_grid_address)[4][3] = (int(*)[4][3])relative_grid_address_py->data; const int *mesh = (int*)mesh_py->data; SPGCONST int (*triplets)[3] = (int(*)[3])triplets_py->data; const int num_triplets = (int)triplets_py->dimensions[0]; SPGCONST int (*bz_grid_address)[3] = (int(*)[3])bz_grid_address_py->data; const int *bz_map = (int*)bz_map_py->data; const double *frequencies = (double*)frequencies_py->data; const int num_band = (int)frequencies_py->dimensions[1]; const int num_iw = (int)iw_py->dimensions[0]; int i, j, k, l, b1, b2, sign; int tp_relative_grid_address[2][24][4][3]; int vertices[2][24][4]; int adrs_shift; double f0, f1, f2, g0, g1, g2; double freq_vertices[3][24][4]; for (i = 0; i < 2; i++) { sign = 1 - i * 2; for (j = 0; j < 24; j++) { for (k = 0; k < 4; k++) { for (l = 0; l < 3; l++) { tp_relative_grid_address[i][j][k][l] = relative_grid_address[j][k][l] * sign; } } } } #pragma omp parallel for private(j, k, b1, b2, vertices, adrs_shift, f0, f1, f2, g0, g1, g2, freq_vertices) for (i = 0; i < num_triplets; i++) { get_triplet_tetrahedra_vertices(vertices, tp_relative_grid_address, mesh, triplets[i], bz_grid_address, bz_map); for (b1 = 0; b1 < num_band; b1++) { for (b2 = 0; b2 < num_band; b2++) { for (j = 0; j < 24; j++) { for (k = 0; k < 4; k++) { f1 = frequencies[vertices[0][j][k] * num_band + b1]; f2 = frequencies[vertices[1][j][k] * num_band + b2]; freq_vertices[0][j][k] = f1 + f2; freq_vertices[1][j][k] = -f1 + f2; freq_vertices[2][j][k] = f1 - f2; } } for (j = 0; j < num_band0; j++) { f0 = frequency_points[j]; g0 = thm_get_integration_weight(f0, freq_vertices[0], 'I'); g1 = thm_get_integration_weight(f0, freq_vertices[1], 'I'); g2 = thm_get_integration_weight(f0, freq_vertices[2], 'I'); adrs_shift = i * num_band0 * num_band * num_band + j * num_band * num_band + b1 * num_band + b2; iw[adrs_shift] = g0; adrs_shift += num_triplets * num_band0 * num_band * num_band; iw[adrs_shift] = g1 - g2; if (num_iw == 3) { adrs_shift += num_triplets * num_band0 * num_band * num_band; iw[adrs_shift] = g0 + g1 + g2; } } } } } Py_RETURN_NONE; }
static PyObject * py_set_integration_weights(PyObject *self, PyObject *args) { PyArrayObject* iw_py; PyArrayObject* frequency_points_py; PyArrayObject* relative_grid_address_py; PyArrayObject* mesh_py; PyArrayObject* grid_points_py; PyArrayObject* frequencies_py; PyArrayObject* bz_grid_address_py; PyArrayObject* bz_map_py; if (!PyArg_ParseTuple(args, "OOOOOOOO", &iw_py, &frequency_points_py, &relative_grid_address_py, &mesh_py, &grid_points_py, &frequencies_py, &bz_grid_address_py, &bz_map_py)) { return NULL; } double *iw = (double*)iw_py->data; const double *frequency_points = (double*)frequency_points_py->data; const int num_band0 = frequency_points_py->dimensions[0]; SPGCONST int (*relative_grid_address)[4][3] = (int(*)[4][3])relative_grid_address_py->data; const int *mesh = (int*)mesh_py->data; SPGCONST int *grid_points = (int*)grid_points_py->data; const int num_gp = (int)grid_points_py->dimensions[0]; SPGCONST int (*bz_grid_address)[3] = (int(*)[3])bz_grid_address_py->data; const int *bz_map = (int*)bz_map_py->data; const double *frequencies = (double*)frequencies_py->data; const int num_band = (int)frequencies_py->dimensions[1]; int i, j, k, bi; int vertices[24][4]; double freq_vertices[24][4]; #pragma omp parallel for private(j, k, bi, vertices, freq_vertices) for (i = 0; i < num_gp; i++) { for (j = 0; j < 24; j++) { kpt_get_neighboring_grid_points(vertices[j], grid_points[i], relative_grid_address[j], 4, mesh, bz_grid_address, bz_map); } for (bi = 0; bi < num_band; bi++) { for (j = 0; j < 24; j++) { for (k = 0; k < 4; k++) { freq_vertices[j][k] = frequencies[vertices[j][k] * num_band + bi]; } } for (j = 0; j < num_band0; j++) { iw[i * num_band0 * num_band + j * num_band + bi] = thm_get_integration_weight(frequency_points[j], freq_vertices, 'I'); } } } Py_RETURN_NONE; }
/* (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); }