static PyObject * get_ir_reciprocal_mesh(PyObject *self, PyObject *args) { double symprec; PyArrayObject* grid_address_py; PyArrayObject* map; PyArrayObject* mesh; PyArrayObject* is_shift; int is_time_reversal; PyArrayObject* lattice; PyArrayObject* position; PyArrayObject* atom_type; if (!PyArg_ParseTuple(args, "OOOOiOOOd", &grid_address_py, &map, &mesh, &is_shift, &is_time_reversal, &lattice, &position, &atom_type, &symprec)) { return NULL; } SPGCONST double (*lat)[3] = (double(*)[3])PyArray_DATA(lattice); SPGCONST double (*pos)[3] = (double(*)[3])PyArray_DATA(position); const int* types = (int*)PyArray_DATA(atom_type); const int* mesh_int = (int*)PyArray_DATA(mesh); const int* is_shift_int = (int*)PyArray_DATA(is_shift); const int num_atom = PyArray_DIMS(position)[0]; int (*grid_address)[3] = (int(*)[3])PyArray_DATA(grid_address_py); int *map_int = (int*)PyArray_DATA(map); /* num_sym has to be larger than num_sym_from_array_size. */ const int num_ir = spg_get_ir_reciprocal_mesh(grid_address, map_int, mesh_int, is_shift_int, is_time_reversal, lat, pos, types, num_atom, symprec); return PyLong_FromLong((long) num_ir); }
static PyObject * get_ir_reciprocal_mesh(PyObject *self, PyObject *args) { double symprec; PyArrayObject* grid_address_py; PyArrayObject* map; PyArrayObject* mesh; PyArrayObject* is_shift; int is_time_reversal; PyArrayObject* lattice; PyArrayObject* position; PyArrayObject* atom_type; if (!PyArg_ParseTuple(args, "OOOOiOOOd", &grid_address_py, &map, &mesh, &is_shift, &is_time_reversal, &lattice, &position, &atom_type, &symprec)) return NULL; SPGCONST double (*lat)[3] = (double(*)[3])lattice->data; SPGCONST double (*pos)[3] = (double(*)[3])position->data; const int* types = (int*)atom_type->data; const int* mesh_int = (int*)mesh->data; const int* is_shift_int = (int*)is_shift->data; const int num_atom = position->dimensions[0]; int (*grid_address)[3] = (int(*)[3])grid_address_py->data; int *map_int = (int*)map->data; /* num_sym has to be larger than num_sym_from_array_size. */ const int num_ir = spg_get_ir_reciprocal_mesh(grid_address, map_int, mesh_int, is_shift_int, is_time_reversal, lat, pos, types, num_atom, symprec); return PyInt_FromLong((long) num_ir); }
static int test_spg_get_ir_reciprocal_mesh(void) { double lattice[3][3] = {{4, 0, 0}, {0, 4, 0}, {0, 0, 3}}; double position[][3] = { {0, 0, 0}, {0.5, 0.5, 0.5}, {0.3, 0.3, 0}, {0.7, 0.7, 0}, {0.2, 0.8, 0.5}, {0.8, 0.2, 0.5}, }; int types[] = {1, 1, 2, 2, 2, 2}; int num_atom = 6; int m = 40; int mesh[] = {m, m, m}; int is_shift[] = {1, 1, 1}; int grid_address[m * m * m][3]; int grid_mapping_table[m * m * m]; printf("*** spg_get_ir_reciprocal_mesh of Rutile structure ***:\n"); int num_ir = spg_get_ir_reciprocal_mesh(grid_address, grid_mapping_table, mesh, is_shift, 1, lattice, position, types, num_atom, 1e-5); if (num_ir) { printf("Number of irreducible k-points of Rutile with\n"); printf("40x40x40 Monkhorst-Pack mesh is %d (4200).\n", num_ir); return 0; } else { return 1; } }
static PyObject * get_ir_reciprocal_mesh(PyObject *self, PyObject *args) { int i, j; double symprec; PyArrayObject* grid_point; PyArrayObject* map; PyArrayObject* mesh; PyArrayObject* is_shift; int is_time_reversal; PyArrayObject* lattice; PyArrayObject* position; PyArrayObject* atom_type; if (!PyArg_ParseTuple(args, "OOOOiOOOd", &grid_point, &map, &mesh, &is_shift, &is_time_reversal, &lattice, &position, &atom_type, &symprec)) return NULL; SPGCONST double (*lat)[3] = (double(*)[3])lattice->data; SPGCONST double (*pos)[3] = (double(*)[3])position->data; const int num_grid = grid_point->dimensions[0]; const long* types_long = (long*)atom_type->data; const long* mesh_long = (long*)mesh->data; const long* is_shift_long = (long*)is_shift->data; const int num_atom = position->dimensions[0]; long *grid_long = (long*)grid_point->data; int grid_int[num_grid][3]; long *map_long = (long*)map->data; int map_int[num_grid]; int types[num_atom]; for (i = 0; i < num_atom; i++) { types[i] = (int)types_long[i]; } int mesh_int[3]; int is_shift_int[3]; for (i = 0; i < 3; i++) { mesh_int[i] = (int) mesh_long[i]; is_shift_int[i] = (int) is_shift_long[i]; } /* Check memory space */ if (mesh_int[0]*mesh_int[1]*mesh_int[2] > num_grid) { return NULL; } /* num_sym has to be larger than num_sym_from_array_size. */ const int num_ir = spg_get_ir_reciprocal_mesh(grid_int, map_int, mesh_int, is_shift_int, is_time_reversal, lat, pos, types, num_atom, symprec); for (i = 0; i < mesh_int[0] * mesh_int[1] * mesh_int[2]; i++) { for (j = 0; j < 3; j++) grid_long[ i*3 + j ] = (long) grid_int[i][j]; map_long[i] = (long) map_int[i]; } return PyInt_FromLong((long) num_ir); }
/* (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); }