lapack_complex_double phonoc_complex_prod(const lapack_complex_double a, const lapack_complex_double b) { lapack_complex_double c; c = lapack_make_complex_double (lapack_complex_double_real(a) * lapack_complex_double_real(b) - lapack_complex_double_imag(a) * lapack_complex_double_imag(b), lapack_complex_double_imag(a) * lapack_complex_double_real(b) + lapack_complex_double_real(a) * lapack_complex_double_imag(b)); return c; }
static PyObject * py_phonopy_zheev(PyObject *self, PyObject *args) { PyArrayObject* dynamical_matrix; PyArrayObject* eigenvalues; if (!PyArg_ParseTuple(args, "OO", &dynamical_matrix, &eigenvalues)) { return NULL; } const int dimension = (int)dynamical_matrix->dimensions[0]; npy_cdouble *dynmat = (npy_cdouble*)dynamical_matrix->data; double *eigvals = (double*)eigenvalues->data; lapack_complex_double *a; int i, info; a = (lapack_complex_double*) malloc(sizeof(lapack_complex_double) * dimension * dimension); for (i = 0; i < dimension * dimension; i++) { a[i] = lapack_make_complex_double(dynmat[i].real, dynmat[i].imag); } info = phonopy_zheev(eigvals, a, dimension, 'L'); for (i = 0; i < dimension * dimension; i++) { dynmat[i].real = lapack_complex_double_real(a[i]); dynmat[i].imag = lapack_complex_double_imag(a[i]); } free(a); return PyLong_FromLong((long) info); }
static double get_fc3_sum (const int i, const int j, const int k, const int bi, const double *freqs0, const double *freqs1, const double *freqs2, const lapack_complex_double *eigvecs0, const lapack_complex_double *eigvecs1, const lapack_complex_double *eigvecs2, const lapack_complex_double *fc3_reciprocal, const double *masses, const int num_atom, const int num_band, const double cutoff_frequency) { double fff, sum_real, sum_imag; lapack_complex_double fc3_sum; if (freqs1[j] > cutoff_frequency && freqs2[k] > cutoff_frequency) { fff = freqs0[bi] * freqs1[j] * freqs2[k]; fc3_sum = fc3_sum_in_reciprocal_to_normal (bi, j, k, eigvecs0, eigvecs1, eigvecs2, fc3_reciprocal, masses, num_atom); sum_real = lapack_complex_double_real(fc3_sum); sum_imag = lapack_complex_double_imag(fc3_sum); return (sum_real * sum_real + sum_imag * sum_imag) / fff; } else { return 0; } }
static lapack_complex_double fc3_sum_in_reciprocal_to_normal (const int bi0, const int bi1, const int bi2, const lapack_complex_double *eigvecs0, const lapack_complex_double *eigvecs1, const lapack_complex_double *eigvecs2, const lapack_complex_double *fc3_reciprocal, const double *masses, const int num_atom) { int i, j, k, l, m, n, index_l, index_lm, baseIndex; double sum_real, sum_imag, mmm, mass_l, mass_lm; lapack_complex_double eig_prod, eig_prod1; sum_real = 0; sum_imag = 0; for (l = 0; l < num_atom; l++) { mass_l = masses[l]; index_l = l * num_atom * num_atom * 27; for (m = 0; m < num_atom; m++) { mass_lm = mass_l * masses[m]; index_lm = index_l + m * num_atom * 27; for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { eig_prod1 = phonoc_complex_prod (eigvecs0[(l * 3 + i) * num_atom * 3 + bi0], eigvecs1[(m * 3 + j) * num_atom * 3 + bi1]); for (n = 0; n < num_atom; n++) { mmm = 1.0 / sqrt(mass_lm * masses[n]); baseIndex = index_lm + n * 27 + i * 9 + j * 3; for (k = 0; k < 3; k++) { eig_prod = phonoc_complex_prod (eig_prod1, eigvecs2[(n * 3 + k) * num_atom * 3 + bi2]); eig_prod = phonoc_complex_prod (eig_prod, fc3_reciprocal[baseIndex + k]); sum_real += lapack_complex_double_real(eig_prod) * mmm; sum_imag += lapack_complex_double_imag(eig_prod) * mmm; } } } } } } return lapack_make_complex_double(sum_real, sum_imag); }
static void real_to_reciprocal_elements(lapack_complex_double *fc4_rec_elem, const double q[12], const double *fc4, const Darray *shortest_vectors, const Iarray *multiplicity, const int *p2s, const int *s2p, const int pi0, const int pi1, const int pi2, const int pi3) { int i, j, k, l, m, num_satom; lapack_complex_double phase_factor, phase_factors[3]; double fc4_rec_real[81], fc4_rec_imag[81]; int fc4_elem_address; for (i = 0; i < 81; i++) { fc4_rec_real[i] = 0; fc4_rec_imag[i] = 0; } num_satom = multiplicity->dims[0]; i = p2s[pi0]; for (j = 0; j < num_satom; j++) { if (s2p[j] != p2s[pi1]) { continue; } phase_factors[0] = get_phase_factor(q, shortest_vectors, multiplicity, pi0, j, 1); for (k = 0; k < num_satom; k++) { if (s2p[k] != p2s[pi2]) { continue; } phase_factors[1] = get_phase_factor(q, shortest_vectors, multiplicity, pi0, k, 2); for (l = 0; l < num_satom; l++) { if (s2p[l] != p2s[pi3]) { continue; } phase_factors[2] = get_phase_factor(q, shortest_vectors, multiplicity, pi0, l, 3); fc4_elem_address = (i * 81 * num_satom * num_satom * num_satom + j * 81 * num_satom * num_satom + k * 81 * num_satom + l * 81); phase_factor = phonoc_complex_prod(phase_factors[0], phase_factors[1]); phase_factor = phonoc_complex_prod(phase_factor, phase_factors[2]); for (m = 0; m < 81; m++) { fc4_rec_real[m] += lapack_complex_double_real(phase_factor) * fc4[fc4_elem_address + m]; fc4_rec_imag[m] += lapack_complex_double_imag(phase_factor) * fc4[fc4_elem_address + m]; } } } } for (i = 0; i < 81; i++) { fc4_rec_elem[i] = lapack_make_complex_double(fc4_rec_real[i], fc4_rec_imag[i]); } }
void get_thm_isotope_scattering_strength(double *collision, const int grid_point, const int *ir_grid_points, const double *mass_variances, const double *frequencies, const lapack_complex_double *eigenvectors, const int num_grid_points, const int *band_indices, const double *occupations, //occupation const int num_band, const int num_band0, const double *integration_weights, const double cutoff_frequency) { int i, j, k, l, m, gp, bb=num_band0*num_band; double *e0_r, *e0_i, *f0, *n0; double e1_r, e1_i, a, b, f, dist, sum_g_k, n; e0_r = (double*)malloc(sizeof(double) * num_band * num_band0); e0_i = (double*)malloc(sizeof(double) * num_band * num_band0); f0 = (double*)malloc(sizeof(double) * num_band0); n0 = (double*)malloc(sizeof(double) *num_band0); for (i = 0; i < num_band0; i++) { f0[i] = frequencies[grid_point * num_band + band_indices[i]]; n0[i] =occupations[grid_point *num_band0+band_indices[i]]; for (j = 0; j < num_band; j++) { e0_r[i * num_band + j] = lapack_complex_double_real (eigenvectors[grid_point * num_band * num_band + j * num_band + band_indices[i]]); e0_i[i * num_band + j] = lapack_complex_double_imag (eigenvectors[grid_point * num_band * num_band + j * num_band + band_indices[i]]); } } #pragma omp parallel for for (i = 0; i < num_grid_points * num_band0 * num_band; i++) { collision[i] = 0; } #pragma omp parallel for private(j, k, l, m, f, gp, e1_r, e1_i, a, b, dist, sum_g_k, n) for (i = 0; i < num_grid_points; i++) { gp = ir_grid_points[i]; for (j = 0; j < num_band0; j++) { /* band index0 */ if (f0[j] < cutoff_frequency) { continue; } for (k = 0; k < num_band; k++) { /* band index */ sum_g_k = 0; n = occupations[gp *num_band + k]; f = frequencies[gp * num_band + k]; if (f < cutoff_frequency) { continue; } dist = integration_weights[i * bb + j * num_band + k]; for (l = 0; l < num_band / 3; l++) { /* elements */ a = 0; b = 0; for (m = 0; m < 3; m++) { e1_r = lapack_complex_double_real (eigenvectors [gp * num_band * num_band + (l * 3 + m) * num_band + k]); e1_i = lapack_complex_double_imag (eigenvectors [gp * num_band * num_band + (l * 3 + m) * num_band + k]); a += (e0_r[j * num_band + l * 3 + m] * e1_r + e0_i[j * num_band + l * 3 + m] * e1_i); b += (e0_i[j * num_band + l * 3 + m] * e1_r - e0_r[j * num_band + l * 3 + m] * e1_i); } sum_g_k += (a * a + b * b) * mass_variances[l] * dist; } collision[i * bb + j * num_band + k] += sum_g_k *f0[j] * f * (n0[j] * n + (n0[j] + n) / 2); } } } free(n0); free(f0); free(e0_r); free(e0_i); }
void get_isotope_scattering_strength(double *collision, //collision[temp, band0] const int grid_point, const int *ir_grid_points, const double *mass_variances, const double *frequencies, const lapack_complex_double *eigenvectors, const int *band_indices, const double *occupations, //occupation const int num_grid_points, const int num_band, const int num_band0, const double sigma, const double cutoff_frequency) { int i, j, k, l, grid2, bb=num_band0*num_band; double *e0_r, *e0_i, e1_r, e1_i, a, b, f,n, *f0, *n0, sum_g_local, dist; e0_r = (double*)malloc(sizeof(double) * num_band * num_band0); e0_i = (double*)malloc(sizeof(double) * num_band * num_band0); f0 = (double*)malloc(sizeof(double) * num_band0); n0 = (double*)malloc(sizeof(double) *num_band0); for (i = 0; i < num_band0; i++) { f0[i] = frequencies[grid_point * num_band + band_indices[i]]; n0[i] =occupations[grid_point*num_band+band_indices[i]]; for (j = 0; j < num_band; j++) { e0_r[i * num_band + j] = lapack_complex_double_real (eigenvectors[grid_point * num_band * num_band + j * num_band + band_indices[i]]); e0_i[i * num_band + j] = lapack_complex_double_imag (eigenvectors[grid_point * num_band * num_band + j * num_band + band_indices[i]]); } } for (i = 0; i < num_grid_points * num_band0 * num_band; i++) { collision[i] = 0; } #pragma omp parallel for private(i, k, l, f,n, e1_r, e1_i, a, b, sum_g_local, dist, grid2) for (j = 0; j < num_grid_points; j++) { for (i = 0; i < num_band0; i++) { /* band index0 */ if (f0[i] < cutoff_frequency) continue; grid2 = ir_grid_points[j]; for (k = 0; k < num_band; k++) { /* band index */ sum_g_local = 0; f = frequencies[grid2 * num_band + k]; if (f < cutoff_frequency) continue; dist = gaussian(f - f0[i], sigma); for (l = 0; l < num_band; l++) { /* elements */ e1_r = lapack_complex_double_real (eigenvectors[grid2 * num_band * num_band + l * num_band + k]); e1_i = lapack_complex_double_imag (eigenvectors[grid2 * num_band * num_band + l * num_band + k]); a = e0_r[i * num_band + l] * e1_r + e0_i[i * num_band + l] * e1_i; b = e0_i[i * num_band + l] * e1_r - e0_r[i * num_band + l] * e1_i; sum_g_local += (a * a + b * b) * mass_variances[l / 3]; } n=occupations[grid2*num_band+k]; collision[j * bb + i * num_band + k] += sum_g_local * dist * f0[i] * f * (n0[i] * n + (n0[i] + n) / 2); } } } free(n0); free(f0); free(e0_r); free(e0_i); }
/* Auxiliary routine: printing a matrix */ void print_matrix( char* desc, lapack_int m, lapack_int n, lapack_complex_double* a, lapack_int lda ) { lapack_int i, j; printf( "\n %s\n", desc ); for( i = 0; i < m; i++ ) { for( j = 0; j < n; j++ ) printf( " (%6.2f,%6.2f)", lapack_complex_double_real(a[i*lda+j]), lapack_complex_double_imag(a[i*lda+j]) ); printf( "\n" ); } }