/* Copyright (C) 2015 Atsushi Togo */ /* All rights reserved. */ /* This file is part of phonopy. */ /* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */ /* * Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* * Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in */ /* the documentation and/or other materials provided with the */ /* distribution. */ /* * Neither the name of the phonopy project nor the names of its */ /* contributors may be used to endorse or promote products derived */ /* from this software without specific prior written permission. */ /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */ /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */ /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */ /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */ /* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */ /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */ /* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */ /* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */ /* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */ /* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */ /* POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include // #include "lapack_wrapper.h" #include "phono3py.h" #include "phonoc_array.h" static PyObject *py_get_interaction(PyObject *self, PyObject *args); static PyObject *py_get_pp_collision(PyObject *self, PyObject *args); static PyObject *py_get_pp_collision_with_sigma(PyObject *self, PyObject *args); static PyObject *py_get_imag_self_energy_with_g(PyObject *self, PyObject *args); static PyObject *py_get_detailed_imag_self_energy_with_g(PyObject *self, PyObject *args); static PyObject *py_get_real_self_energy_at_bands(PyObject *self, PyObject *args); static PyObject *py_get_real_self_energy_at_frequency_point(PyObject *self, PyObject *args); static PyObject *py_get_collision_matrix(PyObject *self, PyObject *args); static PyObject *py_get_reducible_collision_matrix(PyObject *self, PyObject *args); static PyObject *py_symmetrize_collision_matrix(PyObject *self, PyObject *args); static PyObject *py_expand_collision_matrix(PyObject *self, PyObject *args); static PyObject *py_distribute_fc3(PyObject *self, PyObject *args); static PyObject *py_rotate_delta_fc2s(PyObject *self, PyObject *args); static PyObject *py_get_isotope_strength(PyObject *self, PyObject *args); static PyObject *py_get_thm_isotope_strength(PyObject *self, PyObject *args); static PyObject *py_get_permutation_symmetry_fc3(PyObject *self, PyObject *args); static PyObject *py_get_permutation_symmetry_compact_fc3(PyObject *self, PyObject *args); static PyObject *py_transpose_compact_fc3(PyObject *self, PyObject *args); static PyObject *py_get_thm_relative_grid_address(PyObject *self, PyObject *args); static PyObject *py_get_neighboring_grid_points(PyObject *self, PyObject *args); static PyObject *py_get_thm_integration_weights_at_grid_points(PyObject *self, PyObject *args); static PyObject *py_tpl_get_triplets_reciprocal_mesh_at_q(PyObject *self, PyObject *args); static PyObject *py_tpl_get_BZ_triplets_at_q(PyObject *self, PyObject *args); static PyObject *py_get_triplets_integration_weights(PyObject *self, PyObject *args); static PyObject *py_get_triplets_integration_weights_with_sigma(PyObject *self, PyObject *args); static PyObject *py_get_grid_index_from_address(PyObject *self, PyObject *args); static PyObject *py_get_gr_grid_addresses(PyObject *self, PyObject *args); static PyObject *py_get_reciprocal_rotations(PyObject *self, PyObject *args); static PyObject *py_transform_rotations(PyObject *self, PyObject *args); static PyObject *py_get_snf3x3(PyObject *self, PyObject *args); static PyObject *py_get_ir_grid_map(PyObject *self, PyObject *args); static PyObject *py_get_bz_grid_addresses(PyObject *self, PyObject *args); static PyObject *py_rotate_bz_grid_addresses(PyObject *self, PyObject *args); static PyObject *py_diagonalize_collision_matrix(PyObject *self, PyObject *args); static PyObject *py_pinv_from_eigensolution(PyObject *self, PyObject *args); static PyObject *py_get_default_colmat_solver(PyObject *self, PyObject *args); static PyObject *py_lapacke_pinv(PyObject *self, PyObject *args); static PyObject *py_get_omp_max_threads(PyObject *self, PyObject *args); static void show_colmat_info(const PyArrayObject *collision_matrix_py, const long i_sigma, const long i_temp, const long adrs_shift); static Larray *convert_to_larray(PyArrayObject *npyary); static Darray *convert_to_darray(PyArrayObject *npyary); struct module_state { PyObject *error; }; #if PY_MAJOR_VERSION >= 3 #define GETSTATE(m) ((struct module_state *)PyModule_GetState(m)) #else #define GETSTATE(m) (&_state) static struct module_state _state; #endif static PyObject *error_out(PyObject *m) { struct module_state *st = GETSTATE(m); PyErr_SetString(st->error, "something bad happened"); return NULL; } static PyMethodDef _phono3py_methods[] = { {"error_out", (PyCFunction)error_out, METH_NOARGS, NULL}, {"interaction", (PyCFunction)py_get_interaction, METH_VARARGS, "Interaction of triplets"}, {"pp_collision", (PyCFunction)py_get_pp_collision, METH_VARARGS, "Collision and ph-ph calculation"}, {"pp_collision_with_sigma", (PyCFunction)py_get_pp_collision_with_sigma, METH_VARARGS, "Collision and ph-ph calculation for smearing method"}, {"imag_self_energy_with_g", (PyCFunction)py_get_imag_self_energy_with_g, METH_VARARGS, "Imaginary part of self energy at frequency points with g"}, {"detailed_imag_self_energy_with_g", (PyCFunction)py_get_detailed_imag_self_energy_with_g, METH_VARARGS, "Detailed contribution to imaginary part of self energy at frequency " "points with g"}, {"real_self_energy_at_bands", (PyCFunction)py_get_real_self_energy_at_bands, METH_VARARGS, "Real part of self energy from third order force constants"}, {"real_self_energy_at_frequency_point", (PyCFunction)py_get_real_self_energy_at_frequency_point, METH_VARARGS, "Real part of self energy from third order force constants at a frequency " "point"}, {"collision_matrix", (PyCFunction)py_get_collision_matrix, METH_VARARGS, "Collision matrix with g"}, {"reducible_collision_matrix", (PyCFunction)py_get_reducible_collision_matrix, METH_VARARGS, "Collision matrix with g for reducible grid points"}, {"symmetrize_collision_matrix", (PyCFunction)py_symmetrize_collision_matrix, METH_VARARGS, "Symmetrize collision matrix"}, {"expand_collision_matrix", (PyCFunction)py_expand_collision_matrix, METH_VARARGS, "Expand collision matrix"}, {"distribute_fc3", (PyCFunction)py_distribute_fc3, METH_VARARGS, "Distribute least fc3 to full fc3"}, {"rotate_delta_fc2s", (PyCFunction)py_rotate_delta_fc2s, METH_VARARGS, "Rotate delta fc2s"}, {"isotope_strength", (PyCFunction)py_get_isotope_strength, METH_VARARGS, "Isotope scattering strength"}, {"thm_isotope_strength", (PyCFunction)py_get_thm_isotope_strength, METH_VARARGS, "Isotope scattering strength for tetrahedron_method"}, {"permutation_symmetry_fc3", (PyCFunction)py_get_permutation_symmetry_fc3, METH_VARARGS, "Set permutation symmetry for fc3"}, {"permutation_symmetry_compact_fc3", (PyCFunction)py_get_permutation_symmetry_compact_fc3, METH_VARARGS, "Set permutation symmetry for compact-fc3"}, {"transpose_compact_fc3", (PyCFunction)py_transpose_compact_fc3, METH_VARARGS, "Transpose compact fc3"}, {"tetrahedra_relative_grid_address", (PyCFunction)py_get_thm_relative_grid_address, METH_VARARGS, "Relative grid addresses of vertices of 24 tetrahedra"}, {"neighboring_grid_points", (PyCFunction)py_get_neighboring_grid_points, METH_VARARGS, "Neighboring grid points by relative grid addresses"}, {"integration_weights_at_grid_points", (PyCFunction)py_get_thm_integration_weights_at_grid_points, METH_VARARGS, "Integration weights of tetrahedron method at grid points"}, {"triplets_reciprocal_mesh_at_q", (PyCFunction)py_tpl_get_triplets_reciprocal_mesh_at_q, METH_VARARGS, "Triplets on reciprocal mesh points at a specific q-point"}, {"BZ_triplets_at_q", (PyCFunction)py_tpl_get_BZ_triplets_at_q, METH_VARARGS, "Triplets in reciprocal primitive lattice are transformed to those in " "BZ."}, {"triplets_integration_weights", (PyCFunction)py_get_triplets_integration_weights, METH_VARARGS, "Integration weights of tetrahedron method for triplets"}, {"triplets_integration_weights_with_sigma", (PyCFunction)py_get_triplets_integration_weights_with_sigma, METH_VARARGS, "Integration weights of smearing method for triplets"}, {"grid_index_from_address", (PyCFunction)py_get_grid_index_from_address, METH_VARARGS, "Grid index from grid address"}, {"ir_grid_map", (PyCFunction)py_get_ir_grid_map, METH_VARARGS, "Reciprocal mesh points with ir grid mapping table"}, {"gr_grid_addresses", (PyCFunction)py_get_gr_grid_addresses, METH_VARARGS, "Get generalized regular grid addresses"}, {"reciprocal_rotations", (PyCFunction)py_get_reciprocal_rotations, METH_VARARGS, "Return rotation matrices in reciprocal space"}, {"transform_rotations", (PyCFunction)py_transform_rotations, METH_VARARGS, "Transform rotations to those in generalized regular grid"}, {"snf3x3", (PyCFunction)py_get_snf3x3, METH_VARARGS, "Get Smith formal form for 3x3 integer matrix"}, {"bz_grid_addresses", (PyCFunction)py_get_bz_grid_addresses, METH_VARARGS, "Get grid addresses including Brillouin zone surface"}, {"rotate_bz_grid_index", (PyCFunction)py_rotate_bz_grid_addresses, METH_VARARGS, "Rotate grid point considering Brillouin zone surface"}, {"diagonalize_collision_matrix", (PyCFunction)py_diagonalize_collision_matrix, METH_VARARGS, "Diagonalize and optionally pseudo-inverse using Lapack dsyev(d)"}, {"pinv_from_eigensolution", (PyCFunction)py_pinv_from_eigensolution, METH_VARARGS, "Pseudo-inverse from eigensolution"}, {"default_colmat_solver", (PyCFunction)py_get_default_colmat_solver, METH_VARARGS, "Return default collison matrix solver by integer value"}, {"lapacke_pinv", (PyCFunction)py_lapacke_pinv, METH_VARARGS, "Pseudo inversion using lapacke."}, {"omp_max_threads", py_get_omp_max_threads, METH_VARARGS, "Return openmp max number of threads. Return 0 unless openmp is " "activated. "}, {NULL, NULL, 0, NULL}}; #if PY_MAJOR_VERSION >= 3 static int _phono3py_traverse(PyObject *m, visitproc visit, void *arg) { Py_VISIT(GETSTATE(m)->error); return 0; } static int _phono3py_clear(PyObject *m) { Py_CLEAR(GETSTATE(m)->error); return 0; } static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "_phono3py", NULL, sizeof(struct module_state), _phono3py_methods, NULL, _phono3py_traverse, _phono3py_clear, NULL}; #define INITERROR return NULL PyObject *PyInit__phono3py(void) #else #define INITERROR return void init_phono3py(void) #endif { #if PY_MAJOR_VERSION >= 3 PyObject *module = PyModule_Create(&moduledef); #else PyObject *module = Py_InitModule("_phono3py", _phono3py_methods); #endif struct module_state *st; if (module == NULL) INITERROR; st = GETSTATE(module); st->error = PyErr_NewException("_phono3py.Error", NULL, NULL); if (st->error == NULL) { Py_DECREF(module); INITERROR; } #if PY_MAJOR_VERSION >= 3 return module; #endif } static PyObject *py_get_interaction(PyObject *self, PyObject *args) { PyArrayObject *py_fc3_normal_squared; PyArrayObject *py_g_zero; PyArrayObject *py_frequencies; PyArrayObject *py_eigenvectors; PyArrayObject *py_triplets; PyArrayObject *py_bz_grid_addresses; PyArrayObject *py_D_diag; PyArrayObject *py_Q; PyArrayObject *py_svecs; PyArrayObject *py_multi; PyArrayObject *py_fc3; PyArrayObject *py_masses; PyArrayObject *py_p2s_map; PyArrayObject *py_s2p_map; PyArrayObject *py_band_indices; PyArrayObject *py_all_shortest; double cutoff_frequency; long symmetrize_fc3_q; long make_r0_average; long openmp_per_triplets; Darray *fc3_normal_squared; Darray *freqs; _lapack_complex_double *eigvecs; long(*triplets)[3]; long num_triplets; char *g_zero; long(*bz_grid_addresses)[3]; long *D_diag; long(*Q)[3]; double *fc3; double(*svecs)[3]; long(*multi)[2]; double *masses; char *all_shortest; long *p2s; long *s2p; long *band_indices; long multi_dims[2]; long i; long is_compact_fc3; if (!PyArg_ParseTuple(args, "OOOOOOOOOOOOOOOllOdl", &py_fc3_normal_squared, &py_g_zero, &py_frequencies, &py_eigenvectors, &py_triplets, &py_bz_grid_addresses, &py_D_diag, &py_Q, &py_fc3, &py_svecs, &py_multi, &py_masses, &py_p2s_map, &py_s2p_map, &py_band_indices, &symmetrize_fc3_q, &make_r0_average, &py_all_shortest, &cutoff_frequency, &openmp_per_triplets)) { return NULL; } fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); freqs = convert_to_darray(py_frequencies); /* npy_cdouble and lapack_complex_double may not be compatible. */ /* So eigenvectors should not be used in Python side */ eigvecs = (_lapack_complex_double *)PyArray_DATA(py_eigenvectors); triplets = (long(*)[3])PyArray_DATA(py_triplets); num_triplets = (long)PyArray_DIMS(py_triplets)[0]; g_zero = (char *)PyArray_DATA(py_g_zero); bz_grid_addresses = (long(*)[3])PyArray_DATA(py_bz_grid_addresses); D_diag = (long *)PyArray_DATA(py_D_diag); Q = (long(*)[3])PyArray_DATA(py_Q); fc3 = (double *)PyArray_DATA(py_fc3); if (PyArray_DIMS(py_fc3)[0] == PyArray_DIMS(py_fc3)[1]) { is_compact_fc3 = 0; } else { is_compact_fc3 = 1; } svecs = (double(*)[3])PyArray_DATA(py_svecs); for (i = 0; i < 2; i++) { multi_dims[i] = PyArray_DIMS(py_multi)[i]; } multi = (long(*)[2])PyArray_DATA(py_multi); masses = (double *)PyArray_DATA(py_masses); p2s = (long *)PyArray_DATA(py_p2s_map); s2p = (long *)PyArray_DATA(py_s2p_map); band_indices = (long *)PyArray_DATA(py_band_indices); all_shortest = (char *)PyArray_DATA(py_all_shortest); ph3py_get_interaction(fc3_normal_squared, g_zero, freqs, eigvecs, triplets, num_triplets, bz_grid_addresses, D_diag, Q, fc3, is_compact_fc3, svecs, multi_dims, multi, masses, p2s, s2p, band_indices, symmetrize_fc3_q, make_r0_average, all_shortest, cutoff_frequency, openmp_per_triplets); free(fc3_normal_squared); fc3_normal_squared = NULL; free(freqs); freqs = NULL; Py_RETURN_NONE; } static PyObject *py_get_pp_collision(PyObject *self, PyObject *args) { PyArrayObject *py_gamma; PyArrayObject *py_relative_grid_address; PyArrayObject *py_frequencies; PyArrayObject *py_eigenvectors; PyArrayObject *py_triplets; PyArrayObject *py_triplet_weights; PyArrayObject *py_bz_grid_addresses; PyArrayObject *py_bz_map; PyArrayObject *py_D_diag; PyArrayObject *py_Q; PyArrayObject *py_fc3; PyArrayObject *py_svecs; PyArrayObject *py_multi; PyArrayObject *py_masses; PyArrayObject *py_p2s_map; PyArrayObject *py_s2p_map; PyArrayObject *py_band_indices; PyArrayObject *py_temperatures; PyArrayObject *py_all_shortest; double cutoff_frequency; long is_NU; long symmetrize_fc3_q; long make_r0_average; long bz_grid_type; long openmp_per_triplets; double *gamma; long(*relative_grid_address)[4][3]; double *frequencies; _lapack_complex_double *eigenvectors; long(*triplets)[3]; long num_triplets; long *triplet_weights; long(*bz_grid_addresses)[3]; long *bz_map; long *D_diag; long(*Q)[3]; double *fc3; double(*svecs)[3]; long(*multi)[2]; double *masses; long *p2s; long *s2p; Larray *band_indices; Darray *temperatures; char *all_shortest; long multi_dims[2]; long i; long is_compact_fc3; if (!PyArg_ParseTuple( args, "OOOOOOOOlOOOOOOOOOOlllOdl", &py_gamma, &py_relative_grid_address, &py_frequencies, &py_eigenvectors, &py_triplets, &py_triplet_weights, &py_bz_grid_addresses, &py_bz_map, &bz_grid_type, &py_D_diag, &py_Q, &py_fc3, &py_svecs, &py_multi, &py_masses, &py_p2s_map, &py_s2p_map, &py_band_indices, &py_temperatures, &is_NU, &symmetrize_fc3_q, &make_r0_average, &py_all_shortest, &cutoff_frequency, &openmp_per_triplets)) { return NULL; } gamma = (double *)PyArray_DATA(py_gamma); relative_grid_address = (long(*)[4][3])PyArray_DATA(py_relative_grid_address); frequencies = (double *)PyArray_DATA(py_frequencies); eigenvectors = (_lapack_complex_double *)PyArray_DATA(py_eigenvectors); triplets = (long(*)[3])PyArray_DATA(py_triplets); num_triplets = (long)PyArray_DIMS(py_triplets)[0]; triplet_weights = (long *)PyArray_DATA(py_triplet_weights); bz_grid_addresses = (long(*)[3])PyArray_DATA(py_bz_grid_addresses); bz_map = (long *)PyArray_DATA(py_bz_map); D_diag = (long *)PyArray_DATA(py_D_diag); Q = (long(*)[3])PyArray_DATA(py_Q); fc3 = (double *)PyArray_DATA(py_fc3); if (PyArray_DIMS(py_fc3)[0] == PyArray_DIMS(py_fc3)[1]) { is_compact_fc3 = 0; } else { is_compact_fc3 = 1; } svecs = (double(*)[3])PyArray_DATA(py_svecs); for (i = 0; i < 2; i++) { multi_dims[i] = PyArray_DIMS(py_multi)[i]; } multi = (long(*)[2])PyArray_DATA(py_multi); masses = (double *)PyArray_DATA(py_masses); p2s = (long *)PyArray_DATA(py_p2s_map); s2p = (long *)PyArray_DATA(py_s2p_map); band_indices = convert_to_larray(py_band_indices); temperatures = convert_to_darray(py_temperatures); all_shortest = (char *)PyArray_DATA(py_all_shortest); ph3py_get_pp_collision( gamma, relative_grid_address, frequencies, eigenvectors, triplets, num_triplets, triplet_weights, bz_grid_addresses, bz_map, bz_grid_type, D_diag, Q, fc3, is_compact_fc3, svecs, multi_dims, multi, masses, p2s, s2p, band_indices, temperatures, is_NU, symmetrize_fc3_q, make_r0_average, all_shortest, cutoff_frequency, openmp_per_triplets); free(band_indices); band_indices = NULL; free(temperatures); temperatures = NULL; Py_RETURN_NONE; } static PyObject *py_get_pp_collision_with_sigma(PyObject *self, PyObject *args) { PyArrayObject *py_gamma; PyArrayObject *py_frequencies; PyArrayObject *py_eigenvectors; PyArrayObject *py_triplets; PyArrayObject *py_triplet_weights; PyArrayObject *py_bz_grid_addresses; PyArrayObject *py_D_diag; PyArrayObject *py_Q; PyArrayObject *py_fc3; PyArrayObject *py_svecs; PyArrayObject *py_multi; PyArrayObject *py_masses; PyArrayObject *py_p2s_map; PyArrayObject *py_s2p_map; PyArrayObject *py_band_indices; PyArrayObject *py_temperatures; PyArrayObject *py_all_shortest; long is_NU; long symmetrize_fc3_q; double sigma; double sigma_cutoff; long make_r0_average; double cutoff_frequency; long openmp_per_triplets; double *gamma; double *frequencies; _lapack_complex_double *eigenvectors; long(*triplets)[3]; long num_triplets; long *triplet_weights; long(*bz_grid_addresses)[3]; long *D_diag; long(*Q)[3]; double *fc3; double(*svecs)[3]; long(*multi)[2]; double *masses; long *p2s; long *s2p; Larray *band_indices; Darray *temperatures; char *all_shortest; long multi_dims[2]; long i; long is_compact_fc3; if (!PyArg_ParseTuple( args, "OddOOOOOOOOOOOOOOOlllOdl", &py_gamma, &sigma, &sigma_cutoff, &py_frequencies, &py_eigenvectors, &py_triplets, &py_triplet_weights, &py_bz_grid_addresses, &py_D_diag, &py_Q, &py_fc3, &py_svecs, &py_multi, &py_masses, &py_p2s_map, &py_s2p_map, &py_band_indices, &py_temperatures, &is_NU, &symmetrize_fc3_q, &make_r0_average, &py_all_shortest, &cutoff_frequency, &openmp_per_triplets)) { return NULL; } gamma = (double *)PyArray_DATA(py_gamma); frequencies = (double *)PyArray_DATA(py_frequencies); eigenvectors = (_lapack_complex_double *)PyArray_DATA(py_eigenvectors); triplets = (long(*)[3])PyArray_DATA(py_triplets); num_triplets = (long)PyArray_DIMS(py_triplets)[0]; triplet_weights = (long *)PyArray_DATA(py_triplet_weights); bz_grid_addresses = (long(*)[3])PyArray_DATA(py_bz_grid_addresses); D_diag = (long *)PyArray_DATA(py_D_diag); Q = (long(*)[3])PyArray_DATA(py_Q); fc3 = (double *)PyArray_DATA(py_fc3); if (PyArray_DIMS(py_fc3)[0] == PyArray_DIMS(py_fc3)[1]) { is_compact_fc3 = 0; } else { is_compact_fc3 = 1; } svecs = (double(*)[3])PyArray_DATA(py_svecs); for (i = 0; i < 2; i++) { multi_dims[i] = PyArray_DIMS(py_multi)[i]; } multi = (long(*)[2])PyArray_DATA(py_multi); masses = (double *)PyArray_DATA(py_masses); p2s = (long *)PyArray_DATA(py_p2s_map); s2p = (long *)PyArray_DATA(py_s2p_map); band_indices = convert_to_larray(py_band_indices); temperatures = convert_to_darray(py_temperatures); all_shortest = (char *)PyArray_DATA(py_all_shortest); ph3py_get_pp_collision_with_sigma( gamma, sigma, sigma_cutoff, frequencies, eigenvectors, triplets, num_triplets, triplet_weights, bz_grid_addresses, D_diag, Q, fc3, is_compact_fc3, svecs, multi_dims, multi, masses, p2s, s2p, band_indices, temperatures, is_NU, symmetrize_fc3_q, make_r0_average, all_shortest, cutoff_frequency, openmp_per_triplets); free(band_indices); band_indices = NULL; free(temperatures); temperatures = NULL; Py_RETURN_NONE; } static PyObject *py_get_imag_self_energy_with_g(PyObject *self, PyObject *args) { PyArrayObject *py_gamma; PyArrayObject *py_fc3_normal_squared; PyArrayObject *py_frequencies; PyArrayObject *py_triplets; PyArrayObject *py_triplet_weights; PyArrayObject *py_g; PyArrayObject *py_g_zero; double cutoff_frequency, temperature; long frequency_point_index; Darray *fc3_normal_squared; double *gamma; double *g; char *g_zero; double *frequencies; long(*triplets)[3]; long *triplet_weights; long num_frequency_points; if (!PyArg_ParseTuple(args, "OOOOOdOOdl", &py_gamma, &py_fc3_normal_squared, &py_triplets, &py_triplet_weights, &py_frequencies, &temperature, &py_g, &py_g_zero, &cutoff_frequency, &frequency_point_index)) { return NULL; } fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); gamma = (double *)PyArray_DATA(py_gamma); g = (double *)PyArray_DATA(py_g); g_zero = (char *)PyArray_DATA(py_g_zero); frequencies = (double *)PyArray_DATA(py_frequencies); triplets = (long(*)[3])PyArray_DATA(py_triplets); triplet_weights = (long *)PyArray_DATA(py_triplet_weights); num_frequency_points = (long)PyArray_DIMS(py_g)[2]; ph3py_get_imag_self_energy_at_bands_with_g( gamma, fc3_normal_squared, frequencies, triplets, triplet_weights, g, g_zero, temperature, cutoff_frequency, num_frequency_points, frequency_point_index); free(fc3_normal_squared); fc3_normal_squared = NULL; Py_RETURN_NONE; } static PyObject *py_get_detailed_imag_self_energy_with_g(PyObject *self, PyObject *args) { PyArrayObject *py_gamma_detail; PyArrayObject *py_gamma_N; PyArrayObject *py_gamma_U; PyArrayObject *py_fc3_normal_squared; PyArrayObject *py_frequencies; PyArrayObject *py_triplets; PyArrayObject *py_triplet_weights; PyArrayObject *py_bz_grid_addresses; PyArrayObject *py_g; PyArrayObject *py_g_zero; double cutoff_frequency, temperature; Darray *fc3_normal_squared; double *gamma_detail; double *gamma_N; double *gamma_U; double *g; char *g_zero; double *frequencies; long(*triplets)[3]; long *triplet_weights; long(*bz_grid_addresses)[3]; if (!PyArg_ParseTuple(args, "OOOOOOOOdOOd", &py_gamma_detail, &py_gamma_N, &py_gamma_U, &py_fc3_normal_squared, &py_triplets, &py_triplet_weights, &py_bz_grid_addresses, &py_frequencies, &temperature, &py_g, &py_g_zero, &cutoff_frequency)) { return NULL; } fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); gamma_detail = (double *)PyArray_DATA(py_gamma_detail); gamma_N = (double *)PyArray_DATA(py_gamma_N); gamma_U = (double *)PyArray_DATA(py_gamma_U); g = (double *)PyArray_DATA(py_g); g_zero = (char *)PyArray_DATA(py_g_zero); frequencies = (double *)PyArray_DATA(py_frequencies); triplets = (long(*)[3])PyArray_DATA(py_triplets); triplet_weights = (long *)PyArray_DATA(py_triplet_weights); bz_grid_addresses = (long(*)[3])PyArray_DATA(py_bz_grid_addresses); ph3py_get_detailed_imag_self_energy_at_bands_with_g( gamma_detail, gamma_N, gamma_U, fc3_normal_squared, frequencies, triplets, triplet_weights, bz_grid_addresses, g, g_zero, temperature, cutoff_frequency); free(fc3_normal_squared); fc3_normal_squared = NULL; Py_RETURN_NONE; } static PyObject *py_get_real_self_energy_at_bands(PyObject *self, PyObject *args) { PyArrayObject *py_shift; PyArrayObject *py_fc3_normal_squared; PyArrayObject *py_frequencies; PyArrayObject *py_triplets; PyArrayObject *py_triplet_weights; PyArrayObject *py_band_indices; double epsilon, unit_conversion_factor, cutoff_frequency, temperature; Darray *fc3_normal_squared; double *shift; double *frequencies; long *band_indices; long(*triplets)[3]; long *triplet_weights; if (!PyArg_ParseTuple(args, "OOOOOOdddd", &py_shift, &py_fc3_normal_squared, &py_triplets, &py_triplet_weights, &py_frequencies, &py_band_indices, &temperature, &epsilon, &unit_conversion_factor, &cutoff_frequency)) { return NULL; } fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); shift = (double *)PyArray_DATA(py_shift); frequencies = (double *)PyArray_DATA(py_frequencies); band_indices = (long *)PyArray_DATA(py_band_indices); triplets = (long(*)[3])PyArray_DATA(py_triplets); triplet_weights = (long *)PyArray_DATA(py_triplet_weights); ph3py_get_real_self_energy_at_bands( shift, fc3_normal_squared, band_indices, frequencies, triplets, triplet_weights, epsilon, temperature, unit_conversion_factor, cutoff_frequency); free(fc3_normal_squared); fc3_normal_squared = NULL; Py_RETURN_NONE; } static PyObject *py_get_real_self_energy_at_frequency_point(PyObject *self, PyObject *args) { PyArrayObject *py_shift; PyArrayObject *py_fc3_normal_squared; PyArrayObject *py_frequencies; PyArrayObject *py_triplets; PyArrayObject *py_triplet_weights; PyArrayObject *py_band_indices; double frequency_point, epsilon, unit_conversion_factor, cutoff_frequency; double temperature; Darray *fc3_normal_squared; double *shift; double *frequencies; long *band_indices; long(*triplets)[3]; long *triplet_weights; if (!PyArg_ParseTuple(args, "OdOOOOOdddd", &py_shift, &frequency_point, &py_fc3_normal_squared, &py_triplets, &py_triplet_weights, &py_frequencies, &py_band_indices, &temperature, &epsilon, &unit_conversion_factor, &cutoff_frequency)) { return NULL; } fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); shift = (double *)PyArray_DATA(py_shift); frequencies = (double *)PyArray_DATA(py_frequencies); band_indices = (long *)PyArray_DATA(py_band_indices); triplets = (long(*)[3])PyArray_DATA(py_triplets); triplet_weights = (long *)PyArray_DATA(py_triplet_weights); ph3py_get_real_self_energy_at_frequency_point( shift, frequency_point, fc3_normal_squared, band_indices, frequencies, triplets, triplet_weights, epsilon, temperature, unit_conversion_factor, cutoff_frequency); free(fc3_normal_squared); fc3_normal_squared = NULL; Py_RETURN_NONE; } static PyObject *py_get_collision_matrix(PyObject *self, PyObject *args) { PyArrayObject *py_collision_matrix; PyArrayObject *py_fc3_normal_squared; PyArrayObject *py_frequencies; PyArrayObject *py_triplets; PyArrayObject *py_triplets_map; PyArrayObject *py_map_q; PyArrayObject *py_g; PyArrayObject *py_rotated_grid_points; PyArrayObject *py_rotations_cartesian; double temperature, unit_conversion_factor, cutoff_frequency; Darray *fc3_normal_squared; double *collision_matrix; double *g; double *frequencies; long(*triplets)[3]; long *triplets_map; long *map_q; long *rotated_grid_points; long num_gp, num_ir_gp, num_rot; double *rotations_cartesian; if (!PyArg_ParseTuple( args, "OOOOOOOOOddd", &py_collision_matrix, &py_fc3_normal_squared, &py_frequencies, &py_g, &py_triplets, &py_triplets_map, &py_map_q, &py_rotated_grid_points, &py_rotations_cartesian, &temperature, &unit_conversion_factor, &cutoff_frequency)) { return NULL; } fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); collision_matrix = (double *)PyArray_DATA(py_collision_matrix); g = (double *)PyArray_DATA(py_g); frequencies = (double *)PyArray_DATA(py_frequencies); triplets = (long(*)[3])PyArray_DATA(py_triplets); triplets_map = (long *)PyArray_DATA(py_triplets_map); num_gp = (long)PyArray_DIMS(py_triplets_map)[0]; map_q = (long *)PyArray_DATA(py_map_q); rotated_grid_points = (long *)PyArray_DATA(py_rotated_grid_points); num_ir_gp = (long)PyArray_DIMS(py_rotated_grid_points)[0]; num_rot = (long)PyArray_DIMS(py_rotated_grid_points)[1]; rotations_cartesian = (double *)PyArray_DATA(py_rotations_cartesian); assert(num_rot == PyArray_DIMS(py_rotations_cartesian)[0]); assert(num_gp == PyArray_DIMS(py_frequencies)[0]); ph3py_get_collision_matrix(collision_matrix, fc3_normal_squared, frequencies, triplets, triplets_map, map_q, rotated_grid_points, rotations_cartesian, g, num_ir_gp, num_gp, num_rot, temperature, unit_conversion_factor, cutoff_frequency); free(fc3_normal_squared); fc3_normal_squared = NULL; Py_RETURN_NONE; } static PyObject *py_get_reducible_collision_matrix(PyObject *self, PyObject *args) { PyArrayObject *py_collision_matrix; PyArrayObject *py_fc3_normal_squared; PyArrayObject *py_frequencies; PyArrayObject *py_triplets; PyArrayObject *py_triplets_map; PyArrayObject *py_map_q; PyArrayObject *py_g; double temperature, unit_conversion_factor, cutoff_frequency; Darray *fc3_normal_squared; double *collision_matrix; double *g; double *frequencies; long(*triplets)[3]; long *triplets_map; long num_gp; long *map_q; if (!PyArg_ParseTuple( args, "OOOOOOOddd", &py_collision_matrix, &py_fc3_normal_squared, &py_frequencies, &py_g, &py_triplets, &py_triplets_map, &py_map_q, &temperature, &unit_conversion_factor, &cutoff_frequency)) { return NULL; } fc3_normal_squared = convert_to_darray(py_fc3_normal_squared); collision_matrix = (double *)PyArray_DATA(py_collision_matrix); g = (double *)PyArray_DATA(py_g); frequencies = (double *)PyArray_DATA(py_frequencies); triplets = (long(*)[3])PyArray_DATA(py_triplets); triplets_map = (long *)PyArray_DATA(py_triplets_map); num_gp = (long)PyArray_DIMS(py_triplets_map)[0]; map_q = (long *)PyArray_DATA(py_map_q); ph3py_get_reducible_collision_matrix( collision_matrix, fc3_normal_squared, frequencies, triplets, triplets_map, map_q, g, num_gp, temperature, unit_conversion_factor, cutoff_frequency); free(fc3_normal_squared); fc3_normal_squared = NULL; Py_RETURN_NONE; } static PyObject *py_symmetrize_collision_matrix(PyObject *self, PyObject *args) { PyArrayObject *py_collision_matrix; double *collision_matrix; long num_band, num_grid_points, num_temp, num_sigma; long num_column; if (!PyArg_ParseTuple(args, "O", &py_collision_matrix)) { return NULL; } collision_matrix = (double *)PyArray_DATA(py_collision_matrix); num_sigma = (long)PyArray_DIMS(py_collision_matrix)[0]; num_temp = (long)PyArray_DIMS(py_collision_matrix)[1]; num_grid_points = (long)PyArray_DIMS(py_collision_matrix)[2]; num_band = (long)PyArray_DIMS(py_collision_matrix)[3]; if (PyArray_NDIM(py_collision_matrix) == 8) { num_column = num_grid_points * num_band * 3; } else { num_column = num_grid_points * num_band; } ph3py_symmetrize_collision_matrix(collision_matrix, num_column, num_temp, num_sigma); Py_RETURN_NONE; } static PyObject *py_expand_collision_matrix(PyObject *self, PyObject *args) { PyArrayObject *py_collision_matrix; PyArrayObject *py_ir_grid_points; PyArrayObject *py_rot_grid_points; double *collision_matrix; long *rot_grid_points; long *ir_grid_points; long num_band, num_grid_points, num_temp, num_sigma, num_rot, num_ir_gp; if (!PyArg_ParseTuple(args, "OOO", &py_collision_matrix, &py_ir_grid_points, &py_rot_grid_points)) { return NULL; } collision_matrix = (double *)PyArray_DATA(py_collision_matrix); rot_grid_points = (long *)PyArray_DATA(py_rot_grid_points); ir_grid_points = (long *)PyArray_DATA(py_ir_grid_points); num_sigma = (long)PyArray_DIMS(py_collision_matrix)[0]; num_temp = (long)PyArray_DIMS(py_collision_matrix)[1]; num_grid_points = (long)PyArray_DIMS(py_collision_matrix)[2]; num_band = (long)PyArray_DIMS(py_collision_matrix)[3]; num_rot = (long)PyArray_DIMS(py_rot_grid_points)[0]; num_ir_gp = (long)PyArray_DIMS(py_ir_grid_points)[0]; ph3py_expand_collision_matrix(collision_matrix, rot_grid_points, ir_grid_points, num_ir_gp, num_grid_points, num_rot, num_sigma, num_temp, num_band); Py_RETURN_NONE; } static PyObject *py_get_isotope_strength(PyObject *self, PyObject *args) { PyArrayObject *py_gamma; PyArrayObject *py_frequencies; PyArrayObject *py_eigenvectors; PyArrayObject *py_band_indices; PyArrayObject *py_mass_variances; PyArrayObject *py_ir_grid_points; PyArrayObject *py_weights; long grid_point; double cutoff_frequency; double sigma; double *gamma; double *frequencies; long *ir_grid_points; double *weights; _lapack_complex_double *eigenvectors; long *band_indices; double *mass_variances; long num_band, num_band0, num_ir_grid_points; if (!PyArg_ParseTuple(args, "OlOOOOOOdd", &py_gamma, &grid_point, &py_ir_grid_points, &py_weights, &py_mass_variances, &py_frequencies, &py_eigenvectors, &py_band_indices, &sigma, &cutoff_frequency)) { return NULL; } gamma = (double *)PyArray_DATA(py_gamma); frequencies = (double *)PyArray_DATA(py_frequencies); eigenvectors = (_lapack_complex_double *)PyArray_DATA(py_eigenvectors); ir_grid_points = (long *)PyArray_DATA(py_ir_grid_points); weights = (double *)PyArray_DATA(py_weights); band_indices = (long *)PyArray_DATA(py_band_indices); mass_variances = (double *)PyArray_DATA(py_mass_variances); num_band = (long)PyArray_DIMS(py_frequencies)[1]; num_band0 = (long)PyArray_DIMS(py_band_indices)[0]; num_ir_grid_points = (long)PyArray_DIMS(py_ir_grid_points)[0]; ph3py_get_isotope_scattering_strength( gamma, grid_point, ir_grid_points, weights, mass_variances, frequencies, eigenvectors, num_ir_grid_points, band_indices, num_band, num_band0, sigma, cutoff_frequency); Py_RETURN_NONE; } static PyObject *py_get_thm_isotope_strength(PyObject *self, PyObject *args) { PyArrayObject *py_gamma; PyArrayObject *py_frequencies; PyArrayObject *py_eigenvectors; PyArrayObject *py_band_indices; PyArrayObject *py_mass_variances; PyArrayObject *py_ir_grid_points; PyArrayObject *py_weights; PyArrayObject *py_integration_weights; long grid_point; double cutoff_frequency; double *gamma; double *frequencies; long *ir_grid_points; double *weights; _lapack_complex_double *eigenvectors; long *band_indices; double *mass_variances; long num_band, num_band0, num_ir_grid_points; double *integration_weights; if (!PyArg_ParseTuple(args, "OlOOOOOOOd", &py_gamma, &grid_point, &py_ir_grid_points, &py_weights, &py_mass_variances, &py_frequencies, &py_eigenvectors, &py_band_indices, &py_integration_weights, &cutoff_frequency)) { return NULL; } gamma = (double *)PyArray_DATA(py_gamma); frequencies = (double *)PyArray_DATA(py_frequencies); ir_grid_points = (long *)PyArray_DATA(py_ir_grid_points); weights = (double *)PyArray_DATA(py_weights); eigenvectors = (_lapack_complex_double *)PyArray_DATA(py_eigenvectors); band_indices = (long *)PyArray_DATA(py_band_indices); mass_variances = (double *)PyArray_DATA(py_mass_variances); num_band = (long)PyArray_DIMS(py_frequencies)[1]; num_band0 = (long)PyArray_DIMS(py_band_indices)[0]; integration_weights = (double *)PyArray_DATA(py_integration_weights); num_ir_grid_points = (long)PyArray_DIMS(py_ir_grid_points)[0]; ph3py_get_thm_isotope_scattering_strength( gamma, grid_point, ir_grid_points, weights, mass_variances, frequencies, eigenvectors, num_ir_grid_points, band_indices, num_band, num_band0, integration_weights, cutoff_frequency); Py_RETURN_NONE; } static PyObject *py_distribute_fc3(PyObject *self, PyObject *args) { PyArrayObject *force_constants_third; long target; long source; PyArrayObject *rotation_cart_inv; PyArrayObject *atom_mapping_py; double *fc3; double *rot_cart_inv; long *atom_mapping; long num_atom; if (!PyArg_ParseTuple(args, "OllOO", &force_constants_third, &target, &source, &atom_mapping_py, &rotation_cart_inv)) { return NULL; } fc3 = (double *)PyArray_DATA(force_constants_third); rot_cart_inv = (double *)PyArray_DATA(rotation_cart_inv); atom_mapping = (long *)PyArray_DATA(atom_mapping_py); num_atom = (long)PyArray_DIMS(atom_mapping_py)[0]; ph3py_distribute_fc3(fc3, target, source, atom_mapping, num_atom, rot_cart_inv); Py_RETURN_NONE; } static PyObject *py_rotate_delta_fc2s(PyObject *self, PyObject *args) { PyArrayObject *py_fc3; PyArrayObject *py_delta_fc2s; PyArrayObject *py_inv_U; PyArrayObject *py_site_sym_cart; PyArrayObject *py_rot_map_syms; double(*fc3)[3][3][3]; double(*delta_fc2s)[3][3]; double *inv_U; double(*site_sym_cart)[3][3]; long *rot_map_syms; long num_atom, num_disp, num_site_sym; if (!PyArg_ParseTuple(args, "OOOOO", &py_fc3, &py_delta_fc2s, &py_inv_U, &py_site_sym_cart, &py_rot_map_syms)) { return NULL; } /* (num_atom, num_atom, 3, 3, 3) */ fc3 = (double(*)[3][3][3])PyArray_DATA(py_fc3); /* (n_u1, num_atom, num_atom, 3, 3) */ delta_fc2s = (double(*)[3][3])PyArray_DATA(py_delta_fc2s); /* (3, n_u1 * n_sym) */ inv_U = (double *)PyArray_DATA(py_inv_U); /* (n_sym, 3, 3) */ site_sym_cart = (double(*)[3][3])PyArray_DATA(py_site_sym_cart); /* (n_sym, natom) */ rot_map_syms = (long *)PyArray_DATA(py_rot_map_syms); num_atom = (long)PyArray_DIMS(py_fc3)[0]; num_disp = (long)PyArray_DIMS(py_delta_fc2s)[0]; num_site_sym = (long)PyArray_DIMS(py_site_sym_cart)[0]; ph3py_rotate_delta_fc2(fc3, delta_fc2s, inv_U, site_sym_cart, rot_map_syms, num_atom, num_site_sym, num_disp); Py_RETURN_NONE; } static PyObject *py_get_permutation_symmetry_fc3(PyObject *self, PyObject *args) { PyArrayObject *py_fc3; double *fc3; long num_atom; if (!PyArg_ParseTuple(args, "O", &py_fc3)) { return NULL; } fc3 = (double *)PyArray_DATA(py_fc3); num_atom = (long)PyArray_DIMS(py_fc3)[0]; ph3py_get_permutation_symmetry_fc3(fc3, num_atom); Py_RETURN_NONE; } static PyObject *py_get_permutation_symmetry_compact_fc3(PyObject *self, PyObject *args) { PyArrayObject *py_fc3; PyArrayObject *py_permutations; PyArrayObject *py_s2pp_map; PyArrayObject *py_p2s_map; PyArrayObject *py_nsym_list; double *fc3; long *s2pp; long *p2s; long *nsym_list; long *perms; long n_patom, n_satom; if (!PyArg_ParseTuple(args, "OOOOO", &py_fc3, &py_permutations, &py_s2pp_map, &py_p2s_map, &py_nsym_list)) { return NULL; } fc3 = (double *)PyArray_DATA(py_fc3); perms = (long *)PyArray_DATA(py_permutations); s2pp = (long *)PyArray_DATA(py_s2pp_map); p2s = (long *)PyArray_DATA(py_p2s_map); nsym_list = (long *)PyArray_DATA(py_nsym_list); n_patom = (long)PyArray_DIMS(py_fc3)[0]; n_satom = (long)PyArray_DIMS(py_fc3)[1]; ph3py_get_permutation_symmetry_compact_fc3(fc3, p2s, s2pp, nsym_list, perms, n_satom, n_patom); Py_RETURN_NONE; } static PyObject *py_transpose_compact_fc3(PyObject *self, PyObject *args) { PyArrayObject *py_fc3; PyArrayObject *py_permutations; PyArrayObject *py_s2pp_map; PyArrayObject *py_p2s_map; PyArrayObject *py_nsym_list; long t_type; double *fc3; long *s2pp; long *p2s; long *nsym_list; long *perms; long n_patom, n_satom; if (!PyArg_ParseTuple(args, "OOOOOl", &py_fc3, &py_permutations, &py_s2pp_map, &py_p2s_map, &py_nsym_list, &t_type)) { return NULL; } fc3 = (double *)PyArray_DATA(py_fc3); perms = (long *)PyArray_DATA(py_permutations); s2pp = (long *)PyArray_DATA(py_s2pp_map); p2s = (long *)PyArray_DATA(py_p2s_map); nsym_list = (long *)PyArray_DATA(py_nsym_list); n_patom = (long)PyArray_DIMS(py_fc3)[0]; n_satom = (long)PyArray_DIMS(py_fc3)[1]; ph3py_transpose_compact_fc3(fc3, p2s, s2pp, nsym_list, perms, n_satom, n_patom, t_type); Py_RETURN_NONE; } static PyObject *py_get_thm_relative_grid_address(PyObject *self, PyObject *args) { PyArrayObject *py_relative_grid_address; PyArrayObject *py_reciprocal_lattice_py; long(*relative_grid_address)[4][3]; double(*reciprocal_lattice)[3]; if (!PyArg_ParseTuple(args, "OO", &py_relative_grid_address, &py_reciprocal_lattice_py)) { return NULL; } relative_grid_address = (long(*)[4][3])PyArray_DATA(py_relative_grid_address); reciprocal_lattice = (double(*)[3])PyArray_DATA(py_reciprocal_lattice_py); ph3py_get_relative_grid_address(relative_grid_address, reciprocal_lattice); Py_RETURN_NONE; } static PyObject *py_get_neighboring_grid_points(PyObject *self, PyObject *args) { PyArrayObject *py_relative_grid_points; PyArrayObject *py_grid_points; PyArrayObject *py_relative_grid_address; PyArrayObject *py_D_diag; PyArrayObject *py_bz_grid_address; PyArrayObject *py_bz_map; long bz_grid_type; long *relative_grid_points; long *grid_points; long num_grid_points, num_relative_grid_address; long(*relative_grid_address)[3]; long *D_diag; long(*bz_grid_address)[3]; long *bz_map; if (!PyArg_ParseTuple(args, "OOOOOOl", &py_relative_grid_points, &py_grid_points, &py_relative_grid_address, &py_D_diag, &py_bz_grid_address, &py_bz_map, &bz_grid_type)) { return NULL; } relative_grid_points = (long *)PyArray_DATA(py_relative_grid_points); grid_points = (long *)PyArray_DATA(py_grid_points); num_grid_points = (long)PyArray_DIMS(py_grid_points)[0]; relative_grid_address = (long(*)[3])PyArray_DATA(py_relative_grid_address); num_relative_grid_address = (long)PyArray_DIMS(py_relative_grid_address)[0]; D_diag = (long *)PyArray_DATA(py_D_diag); bz_grid_address = (long(*)[3])PyArray_DATA(py_bz_grid_address); bz_map = (long *)PyArray_DATA(py_bz_map); ph3py_get_neighboring_gird_points( relative_grid_points, grid_points, relative_grid_address, D_diag, bz_grid_address, bz_map, bz_grid_type, num_grid_points, num_relative_grid_address); Py_RETURN_NONE; } static PyObject *py_get_thm_integration_weights_at_grid_points(PyObject *self, PyObject *args) { PyArrayObject *py_iw; PyArrayObject *py_frequency_points; PyArrayObject *py_relative_grid_address; PyArrayObject *py_D_diag; PyArrayObject *py_grid_points; PyArrayObject *py_frequencies; PyArrayObject *py_bz_grid_address; PyArrayObject *py_gp2irgp_map; PyArrayObject *py_bz_map; long bz_grid_type; char *function; double *iw; double *frequency_points; long num_frequency_points, num_band, num_gp; long(*relative_grid_address)[4][3]; long *D_diag; long *grid_points; long(*bz_grid_address)[3]; long *bz_map; long *gp2irgp_map; double *frequencies; if (!PyArg_ParseTuple(args, "OOOOOOOOOls", &py_iw, &py_frequency_points, &py_relative_grid_address, &py_D_diag, &py_grid_points, &py_frequencies, &py_bz_grid_address, &py_bz_map, &py_gp2irgp_map, &bz_grid_type, &function)) { return NULL; } iw = (double *)PyArray_DATA(py_iw); frequency_points = (double *)PyArray_DATA(py_frequency_points); num_frequency_points = (long)PyArray_DIMS(py_frequency_points)[0]; relative_grid_address = (long(*)[4][3])PyArray_DATA(py_relative_grid_address); D_diag = (long *)PyArray_DATA(py_D_diag); grid_points = (long *)PyArray_DATA(py_grid_points); num_gp = (long)PyArray_DIMS(py_grid_points)[0]; bz_grid_address = (long(*)[3])PyArray_DATA(py_bz_grid_address); bz_map = (long *)PyArray_DATA(py_bz_map); gp2irgp_map = (long *)PyArray_DATA(py_gp2irgp_map); frequencies = (double *)PyArray_DATA(py_frequencies); num_band = (long)PyArray_DIMS(py_frequencies)[1]; ph3py_get_thm_integration_weights_at_grid_points( iw, frequency_points, num_frequency_points, num_band, num_gp, relative_grid_address, D_diag, grid_points, bz_grid_address, bz_map, bz_grid_type, frequencies, gp2irgp_map, function[0]); Py_RETURN_NONE; } static PyObject *py_tpl_get_triplets_reciprocal_mesh_at_q(PyObject *self, PyObject *args) { PyArrayObject *py_map_triplets; PyArrayObject *py_map_q; PyArrayObject *py_D_diag; PyArrayObject *py_rotations; long fixed_grid_number; long is_time_reversal; long swappable; long *map_triplets; long *map_q; long *D_diag; long(*rot)[3][3]; long num_rot; long num_ir; if (!PyArg_ParseTuple(args, "OOlOlOl", &py_map_triplets, &py_map_q, &fixed_grid_number, &py_D_diag, &is_time_reversal, &py_rotations, &swappable)) { return NULL; } map_triplets = (long *)PyArray_DATA(py_map_triplets); map_q = (long *)PyArray_DATA(py_map_q); D_diag = (long *)PyArray_DATA(py_D_diag); rot = (long(*)[3][3])PyArray_DATA(py_rotations); num_rot = (long)PyArray_DIMS(py_rotations)[0]; num_ir = ph3py_get_triplets_reciprocal_mesh_at_q( map_triplets, map_q, fixed_grid_number, D_diag, is_time_reversal, num_rot, rot, swappable); return PyLong_FromLong(num_ir); } static PyObject *py_tpl_get_BZ_triplets_at_q(PyObject *self, PyObject *args) { PyArrayObject *py_triplets; PyArrayObject *py_bz_grid_address; PyArrayObject *py_bz_map; PyArrayObject *py_map_triplets; PyArrayObject *py_D_diag; PyArrayObject *py_Q; long grid_point; long bz_grid_type; long(*triplets)[3]; long(*bz_grid_address)[3]; long *bz_map; long *map_triplets; long num_map_triplets; long *D_diag; long(*Q)[3]; long num_ir; if (!PyArg_ParseTuple(args, "OlOOOOOl", &py_triplets, &grid_point, &py_bz_grid_address, &py_bz_map, &py_map_triplets, &py_D_diag, &py_Q, &bz_grid_type)) { return NULL; } triplets = (long(*)[3])PyArray_DATA(py_triplets); bz_grid_address = (long(*)[3])PyArray_DATA(py_bz_grid_address); bz_map = (long *)PyArray_DATA(py_bz_map); map_triplets = (long *)PyArray_DATA(py_map_triplets); num_map_triplets = (long)PyArray_DIMS(py_map_triplets)[0]; D_diag = (long *)PyArray_DATA(py_D_diag); Q = (long(*)[3])PyArray_DATA(py_Q); num_ir = ph3py_get_BZ_triplets_at_q(triplets, grid_point, bz_grid_address, bz_map, map_triplets, num_map_triplets, D_diag, Q, bz_grid_type); return PyLong_FromLong(num_ir); } static PyObject *py_get_triplets_integration_weights(PyObject *self, PyObject *args) { PyArrayObject *py_iw; PyArrayObject *py_iw_zero; PyArrayObject *py_frequency_points; PyArrayObject *py_relative_grid_address; PyArrayObject *py_D_diag; PyArrayObject *py_triplets; PyArrayObject *py_frequencies1; PyArrayObject *py_frequencies2; PyArrayObject *py_bz_grid_addresses; PyArrayObject *py_bz_map; long bz_grid_type; long tp_type; double *iw; char *iw_zero; double *frequency_points; long(*relative_grid_address)[4][3]; long *D_diag; long(*triplets)[3]; long(*bz_grid_addresses)[3]; long *bz_map; double *frequencies1, *frequencies2; long num_band0, num_band1, num_band2, num_triplets; if (!PyArg_ParseTuple(args, "OOOOOOOOOOll", &py_iw, &py_iw_zero, &py_frequency_points, &py_relative_grid_address, &py_D_diag, &py_triplets, &py_frequencies1, &py_frequencies2, &py_bz_grid_addresses, &py_bz_map, &bz_grid_type, &tp_type)) { return NULL; } iw = (double *)PyArray_DATA(py_iw); iw_zero = (char *)PyArray_DATA(py_iw_zero); frequency_points = (double *)PyArray_DATA(py_frequency_points); num_band0 = (long)PyArray_DIMS(py_frequency_points)[0]; relative_grid_address = (long(*)[4][3])PyArray_DATA(py_relative_grid_address); D_diag = (long *)PyArray_DATA(py_D_diag); triplets = (long(*)[3])PyArray_DATA(py_triplets); num_triplets = (long)PyArray_DIMS(py_triplets)[0]; bz_grid_addresses = (long(*)[3])PyArray_DATA(py_bz_grid_addresses); bz_map = (long *)PyArray_DATA(py_bz_map); frequencies1 = (double *)PyArray_DATA(py_frequencies1); frequencies2 = (double *)PyArray_DATA(py_frequencies2); num_band1 = (long)PyArray_DIMS(py_frequencies1)[1]; num_band2 = (long)PyArray_DIMS(py_frequencies2)[1]; ph3py_get_integration_weight( iw, iw_zero, frequency_points, num_band0, relative_grid_address, D_diag, triplets, num_triplets, bz_grid_addresses, bz_map, bz_grid_type, frequencies1, num_band1, frequencies2, num_band2, tp_type, 1); Py_RETURN_NONE; } static PyObject *py_get_triplets_integration_weights_with_sigma( PyObject *self, PyObject *args) { PyArrayObject *py_iw; PyArrayObject *py_iw_zero; PyArrayObject *py_frequency_points; PyArrayObject *py_triplets; PyArrayObject *py_frequencies; double sigma, sigma_cutoff; double *iw; char *iw_zero; double *frequency_points; long(*triplets)[3]; double *frequencies; long num_band0, num_band, num_iw, num_triplets; if (!PyArg_ParseTuple(args, "OOOOOdd", &py_iw, &py_iw_zero, &py_frequency_points, &py_triplets, &py_frequencies, &sigma, &sigma_cutoff)) { return NULL; } iw = (double *)PyArray_DATA(py_iw); iw_zero = (char *)PyArray_DATA(py_iw_zero); frequency_points = (double *)PyArray_DATA(py_frequency_points); num_band0 = (long)PyArray_DIMS(py_frequency_points)[0]; triplets = (long(*)[3])PyArray_DATA(py_triplets); num_triplets = (long)PyArray_DIMS(py_triplets)[0]; frequencies = (double *)PyArray_DATA(py_frequencies); num_band = (long)PyArray_DIMS(py_frequencies)[1]; num_iw = (long)PyArray_DIMS(py_iw)[0]; ph3py_get_integration_weight_with_sigma( iw, iw_zero, sigma, sigma_cutoff, frequency_points, num_band0, triplets, num_triplets, frequencies, num_band, num_iw); Py_RETURN_NONE; } static PyObject *py_get_grid_index_from_address(PyObject *self, PyObject *args) { PyArrayObject *py_address; PyArrayObject *py_D_diag; long *address; long *D_diag; long gp; if (!PyArg_ParseTuple(args, "OO", &py_address, &py_D_diag)) { return NULL; } address = (long *)PyArray_DATA(py_address); D_diag = (long *)PyArray_DATA(py_D_diag); gp = ph3py_get_grid_index_from_address(address, D_diag); return PyLong_FromLong(gp); } static PyObject *py_get_gr_grid_addresses(PyObject *self, PyObject *args) { PyArrayObject *py_gr_grid_addresses; PyArrayObject *py_D_diag; long(*gr_grid_addresses)[3]; long *D_diag; if (!PyArg_ParseTuple(args, "OO", &py_gr_grid_addresses, &py_D_diag)) { return NULL; } gr_grid_addresses = (long(*)[3])PyArray_DATA(py_gr_grid_addresses); D_diag = (long *)PyArray_DATA(py_D_diag); ph3py_get_gr_grid_addresses(gr_grid_addresses, D_diag); Py_RETURN_NONE; } static PyObject *py_get_reciprocal_rotations(PyObject *self, PyObject *args) { PyArrayObject *py_rec_rotations; PyArrayObject *py_rotations; long is_time_reversal; long(*rec_rotations)[3][3]; long(*rotations)[3][3]; long num_rot, num_rec_rot; if (!PyArg_ParseTuple(args, "OOl", &py_rec_rotations, &py_rotations, &is_time_reversal)) { return NULL; } rec_rotations = (long(*)[3][3])PyArray_DATA(py_rec_rotations); rotations = (long(*)[3][3])PyArray_DATA(py_rotations); num_rot = (long)PyArray_DIMS(py_rotations)[0]; num_rec_rot = ph3py_get_reciprocal_rotations(rec_rotations, rotations, num_rot, is_time_reversal); return PyLong_FromLong(num_rec_rot); } static PyObject *py_transform_rotations(PyObject *self, PyObject *args) { PyArrayObject *py_transformed_rotations; PyArrayObject *py_rotations; PyArrayObject *py_D_diag; PyArrayObject *py_Q; long(*transformed_rotations)[3][3]; long(*rotations)[3][3]; long *D_diag; long(*Q)[3]; long num_rot, succeeded; if (!PyArg_ParseTuple(args, "OOOO", &py_transformed_rotations, &py_rotations, &py_D_diag, &py_Q)) { return NULL; } transformed_rotations = (long(*)[3][3])PyArray_DATA(py_transformed_rotations); rotations = (long(*)[3][3])PyArray_DATA(py_rotations); D_diag = (long *)PyArray_DATA(py_D_diag); Q = (long(*)[3])PyArray_DATA(py_Q); num_rot = (long)PyArray_DIMS(py_transformed_rotations)[0]; succeeded = ph3py_transform_rotations(transformed_rotations, rotations, num_rot, D_diag, Q); if (succeeded) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } static PyObject *py_get_snf3x3(PyObject *self, PyObject *args) { PyArrayObject *py_D_diag; PyArrayObject *py_P; PyArrayObject *py_Q; PyArrayObject *py_A; long *D_diag; long(*P)[3]; long(*Q)[3]; long(*A)[3]; long succeeded; if (!PyArg_ParseTuple(args, "OOOO", &py_D_diag, &py_P, &py_Q, &py_A)) { return NULL; } D_diag = (long *)PyArray_DATA(py_D_diag); P = (long(*)[3])PyArray_DATA(py_P); Q = (long(*)[3])PyArray_DATA(py_Q); A = (long(*)[3])PyArray_DATA(py_A); succeeded = ph3py_get_snf3x3(D_diag, P, Q, A); if (succeeded) { Py_RETURN_TRUE; } else { Py_RETURN_FALSE; } } static PyObject *py_get_ir_grid_map(PyObject *self, PyObject *args) { PyArrayObject *py_grid_mapping_table; PyArrayObject *py_D_diag; PyArrayObject *py_is_shift; PyArrayObject *py_rotations; long *D_diag; long *is_shift; long(*rot)[3][3]; long num_rot; long *grid_mapping_table; long num_ir; if (!PyArg_ParseTuple(args, "OOOO", &py_grid_mapping_table, &py_D_diag, &py_is_shift, &py_rotations)) { return NULL; } D_diag = (long *)PyArray_DATA(py_D_diag); is_shift = (long *)PyArray_DATA(py_is_shift); rot = (long(*)[3][3])PyArray_DATA(py_rotations); num_rot = (long)PyArray_DIMS(py_rotations)[0]; grid_mapping_table = (long *)PyArray_DATA(py_grid_mapping_table); num_ir = ph3py_get_ir_grid_map(grid_mapping_table, D_diag, is_shift, rot, num_rot); return PyLong_FromLong(num_ir); } static PyObject *py_get_bz_grid_addresses(PyObject *self, PyObject *args) { PyArrayObject *py_bz_grid_addresses; PyArrayObject *py_bz_map; PyArrayObject *py_bzg2grg; PyArrayObject *py_D_diag; PyArrayObject *py_Q; PyArrayObject *py_PS; PyArrayObject *py_reciprocal_lattice; long type; long(*bz_grid_addresses)[3]; long *bz_map; long *bzg2grg; long *D_diag; long(*Q)[3]; long *PS; double(*reciprocal_lattice)[3]; long num_total_gp; if (!PyArg_ParseTuple(args, "OOOOOOOl", &py_bz_grid_addresses, &py_bz_map, &py_bzg2grg, &py_D_diag, &py_Q, &py_PS, &py_reciprocal_lattice, &type)) { return NULL; } bz_grid_addresses = (long(*)[3])PyArray_DATA(py_bz_grid_addresses); bz_map = (long *)PyArray_DATA(py_bz_map); bzg2grg = (long *)PyArray_DATA(py_bzg2grg); D_diag = (long *)PyArray_DATA(py_D_diag); Q = (long(*)[3])PyArray_DATA(py_Q); PS = (long *)PyArray_DATA(py_PS); reciprocal_lattice = (double(*)[3])PyArray_DATA(py_reciprocal_lattice); num_total_gp = ph3py_get_bz_grid_addresses(bz_grid_addresses, bz_map, bzg2grg, D_diag, Q, PS, reciprocal_lattice, type); return PyLong_FromLong(num_total_gp); } static PyObject *py_rotate_bz_grid_addresses(PyObject *self, PyObject *args) { PyArrayObject *py_bz_grid_addresses; PyArrayObject *py_rotation; PyArrayObject *py_bz_map; PyArrayObject *py_D_diag; PyArrayObject *py_PS; long bz_grid_index; long type; long(*bz_grid_addresses)[3]; long(*rotation)[3]; long *bz_map; long *D_diag; long *PS; long ret_bz_gp; if (!PyArg_ParseTuple(args, "lOOOOOl", &bz_grid_index, &py_rotation, &py_bz_grid_addresses, &py_bz_map, &py_D_diag, &py_PS, &type)) { return NULL; } bz_grid_addresses = (long(*)[3])PyArray_DATA(py_bz_grid_addresses); rotation = (long(*)[3])PyArray_DATA(py_rotation); bz_map = (long *)PyArray_DATA(py_bz_map); D_diag = (long *)PyArray_DATA(py_D_diag); PS = (long *)PyArray_DATA(py_PS); ret_bz_gp = ph3py_rotate_bz_grid_index( bz_grid_index, rotation, bz_grid_addresses, bz_map, D_diag, PS, type); return PyLong_FromLong(ret_bz_gp); } static PyObject *py_diagonalize_collision_matrix(PyObject *self, PyObject *args) { PyArrayObject *py_collision_matrix; PyArrayObject *py_eigenvalues; double cutoff; long i_sigma, i_temp, is_pinv, solver; double *collision_matrix; double *eigvals; long num_temp, num_grid_point, num_band; long num_column, adrs_shift; long info; if (!PyArg_ParseTuple(args, "OOlldll", &py_collision_matrix, &py_eigenvalues, &i_sigma, &i_temp, &cutoff, &solver, &is_pinv)) { return NULL; } collision_matrix = (double *)PyArray_DATA(py_collision_matrix); eigvals = (double *)PyArray_DATA(py_eigenvalues); if (PyArray_NDIM(py_collision_matrix) == 2) { num_temp = 1; num_column = (long)PyArray_DIM(py_collision_matrix, 1); } else { num_temp = (long)PyArray_DIM(py_collision_matrix, 1); num_grid_point = (long)PyArray_DIM(py_collision_matrix, 2); num_band = (long)PyArray_DIM(py_collision_matrix, 3); if (PyArray_NDIM(py_collision_matrix) == 8) { num_column = num_grid_point * num_band * 3; } else { num_column = num_grid_point * num_band; } } adrs_shift = (i_sigma * num_column * num_column * num_temp + i_temp * num_column * num_column); /* show_colmat_info(py_collision_matrix, i_sigma, i_temp, adrs_shift); */ info = ph3py_phonopy_dsyev(collision_matrix + adrs_shift, eigvals, num_column, solver); if (is_pinv) { ph3py_pinv_from_eigensolution(collision_matrix + adrs_shift, eigvals, num_column, cutoff, 0); } return PyLong_FromLong(info); } static PyObject *py_pinv_from_eigensolution(PyObject *self, PyObject *args) { PyArrayObject *py_collision_matrix; PyArrayObject *py_eigenvalues; double cutoff; long i_sigma, i_temp, pinv_method; double *collision_matrix; double *eigvals; long num_temp, num_grid_point, num_band; long num_column, adrs_shift; if (!PyArg_ParseTuple(args, "OOlldl", &py_collision_matrix, &py_eigenvalues, &i_sigma, &i_temp, &cutoff, &pinv_method)) { return NULL; } collision_matrix = (double *)PyArray_DATA(py_collision_matrix); eigvals = (double *)PyArray_DATA(py_eigenvalues); num_temp = (long)PyArray_DIMS(py_collision_matrix)[1]; num_grid_point = (long)PyArray_DIMS(py_collision_matrix)[2]; num_band = (long)PyArray_DIMS(py_collision_matrix)[3]; if (PyArray_NDIM(py_collision_matrix) == 8) { num_column = num_grid_point * num_band * 3; } else { num_column = num_grid_point * num_band; } adrs_shift = (i_sigma * num_column * num_column * num_temp + i_temp * num_column * num_column); /* show_colmat_info(py_collision_matrix, i_sigma, i_temp, adrs_shift); */ ph3py_pinv_from_eigensolution(collision_matrix + adrs_shift, eigvals, num_column, cutoff, pinv_method); Py_RETURN_NONE; } static PyObject *py_get_default_colmat_solver(PyObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, "")) { return NULL; } #if defined(MKL_LAPACKE) || defined(SCIPY_MKL_H) return PyLong_FromLong((long)1); #else return PyLong_FromLong((long)4); #endif } static PyObject *py_lapacke_pinv(PyObject *self, PyObject *args) { PyArrayObject *data_in_py; PyArrayObject *data_out_py; double cutoff; int m; int n; double *data_in; double *data_out; int info; if (!PyArg_ParseTuple(args, "OOd", &data_out_py, &data_in_py, &cutoff)) { return NULL; } m = (long)PyArray_DIMS(data_in_py)[0]; n = (long)PyArray_DIMS(data_in_py)[1]; data_in = (double *)PyArray_DATA(data_in_py); data_out = (double *)PyArray_DATA(data_out_py); info = ph3py_phonopy_pinv(data_out, data_in, m, n, cutoff); return PyLong_FromLong((long)info); } static PyObject *py_get_omp_max_threads(PyObject *self, PyObject *args) { return PyLong_FromLong(ph3py_get_max_threads()); } static void show_colmat_info(const PyArrayObject *py_collision_matrix, const long i_sigma, const long i_temp, const long adrs_shift) { long i; printf(" Array_shape:("); for (i = 0; i < PyArray_NDIM(py_collision_matrix); i++) { printf("%d", (int)PyArray_DIM(py_collision_matrix, i)); if (i < PyArray_NDIM(py_collision_matrix) - 1) { printf(","); } else { printf("), "); } } printf("Data shift:%lu [%lu, %lu]\n", adrs_shift, i_sigma, i_temp); } /** * @brief Convert numpy "int_" array to phono3py long array structure. * * @param npyary * @return Larray* */ static Larray *convert_to_larray(PyArrayObject *npyary) { long i; Larray *ary; ary = (Larray *)malloc(sizeof(Larray)); for (i = 0; i < PyArray_NDIM(npyary); i++) { ary->dims[i] = PyArray_DIMS(npyary)[i]; } ary->data = (long *)PyArray_DATA(npyary); return ary; } /** * @brief Convert numpy "double" array to phono3py double array structure. * * @param npyary * @return Darray* * @note PyArray_NDIM receives non-const (PyArrayObject *). */ static Darray *convert_to_darray(PyArrayObject *npyary) { int i; Darray *ary; ary = (Darray *)malloc(sizeof(Darray)); for (i = 0; i < PyArray_NDIM(npyary); i++) { ary->dims[i] = PyArray_DIMS(npyary)[i]; } ary->data = (double *)PyArray_DATA(npyary); return ary; }