Merge pull request #51 from phonopy/refactoring

Refactoring and bug fix of direct solition
This commit is contained in:
Atsushi Togo 2021-11-02 22:24:25 +09:00 committed by GitHub
commit febccc9fe8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 8301 additions and 12299 deletions

View File

@ -33,17 +33,17 @@
/* POSSIBILITY OF SUCH DAMAGE. */
#include <Python.h>
#include <stdio.h>
#include <assert.h>
#include <numpy/arrayobject.h>
#include <stdio.h>
#include "lapack_wrapper.h"
static PyObject *py_phonopy_pinv(PyObject *self, PyObject *args);
static PyObject *py_phonopy_zheev(PyObject *self, PyObject *args);
struct module_state
{
PyObject *error;
struct module_state {
PyObject *error;
};
#if PY_MAJOR_VERSION >= 3
@ -53,50 +53,39 @@ struct module_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 PyObject *error_out(PyObject *m) {
struct module_state *st = GETSTATE(m);
PyErr_SetString(st->error, "something bad happened");
return NULL;
}
static PyMethodDef _lapackepy_methods[] = {
{"error_out", (PyCFunction)error_out, METH_NOARGS, NULL},
{"pinv", py_phonopy_pinv, METH_VARARGS, "Pseudo-inverse using Lapack dgesvd"},
{"pinv", py_phonopy_pinv, METH_VARARGS,
"Pseudo-inverse using Lapack dgesvd"},
{"zheev", py_phonopy_zheev, METH_VARARGS, "Lapack zheev wrapper"},
{NULL, NULL, 0, NULL}};
#if PY_MAJOR_VERSION >= 3
static int _lapackepy_traverse(PyObject *m, visitproc visit, void *arg)
{
Py_VISIT(GETSTATE(m)->error);
return 0;
static int _lapackepy_traverse(PyObject *m, visitproc visit, void *arg) {
Py_VISIT(GETSTATE(m)->error);
return 0;
}
static int _lapackepy_clear(PyObject *m)
{
Py_CLEAR(GETSTATE(m)->error);
return 0;
static int _lapackepy_clear(PyObject *m) {
Py_CLEAR(GETSTATE(m)->error);
return 0;
}
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_lapackepy",
NULL,
sizeof(struct module_state),
_lapackepy_methods,
NULL,
_lapackepy_traverse,
_lapackepy_clear,
NULL};
PyModuleDef_HEAD_INIT, "_lapackepy", NULL,
sizeof(struct module_state), _lapackepy_methods, NULL,
_lapackepy_traverse, _lapackepy_clear, NULL};
#define INITERROR return NULL
PyObject *
PyInit__lapackepy(void)
PyObject *PyInit__lapackepy(void)
#else
#define INITERROR return
@ -104,96 +93,83 @@ void init_lapackepy(void)
#endif
{
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create(&moduledef);
PyObject *module = PyModule_Create(&moduledef);
#else
PyObject *module = Py_InitModule("_lapackepy", _lapackepy_methods);
PyObject *module = Py_InitModule("_lapackepy", _lapackepy_methods);
#endif
struct module_state *st;
struct module_state *st;
if (module == NULL)
INITERROR;
st = GETSTATE(module);
if (module == NULL) INITERROR;
st = GETSTATE(module);
st->error = PyErr_NewException("_lapackepy.Error", NULL, NULL);
if (st->error == NULL)
{
Py_DECREF(module);
INITERROR;
}
st->error = PyErr_NewException("_lapackepy.Error", NULL, NULL);
if (st->error == NULL) {
Py_DECREF(module);
INITERROR;
}
#if PY_MAJOR_VERSION >= 3
return module;
return module;
#endif
}
static PyObject *py_phonopy_zheev(PyObject *self, PyObject *args)
{
PyArrayObject *dynamical_matrix;
PyArrayObject *eigenvalues;
static PyObject *py_phonopy_zheev(PyObject *self, PyObject *args) {
PyArrayObject *dynamical_matrix;
PyArrayObject *eigenvalues;
int dimension;
npy_cdouble *dynmat;
double *eigvals;
lapack_complex_double *a;
int i, info;
int dimension;
npy_cdouble *dynmat;
double *eigvals;
lapack_complex_double *a;
int i, info;
if (!PyArg_ParseTuple(args, "OO",
&dynamical_matrix,
&eigenvalues))
{
return NULL;
}
if (!PyArg_ParseTuple(args, "OO", &dynamical_matrix, &eigenvalues)) {
return NULL;
}
dimension = (int)PyArray_DIMS(dynamical_matrix)[0];
dynmat = (npy_cdouble *)PyArray_DATA(dynamical_matrix);
eigvals = (double *)PyArray_DATA(eigenvalues);
dimension = (int)PyArray_DIMS(dynamical_matrix)[0];
dynmat = (npy_cdouble *)PyArray_DATA(dynamical_matrix);
eigvals = (double *)PyArray_DATA(eigenvalues);
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);
}
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');
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]);
}
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);
free(a);
return PyLong_FromLong((long)info);
return PyLong_FromLong((long)info);
}
static PyObject *py_phonopy_pinv(PyObject *self, PyObject *args)
{
PyArrayObject *data_in_py;
PyArrayObject *data_out_py;
double cutoff;
static PyObject *py_phonopy_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;
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;
}
if (!PyArg_ParseTuple(args, "OOd", &data_out_py, &data_in_py, &cutoff)) {
return NULL;
}
m = (int)PyArray_DIMS(data_in_py)[0];
n = (int)PyArray_DIMS(data_in_py)[1];
data_in = (double *)PyArray_DATA(data_in_py);
data_out = (double *)PyArray_DATA(data_out_py);
m = (int)PyArray_DIMS(data_in_py)[0];
n = (int)PyArray_DIMS(data_in_py)[1];
data_in = (double *)PyArray_DATA(data_in_py);
data_out = (double *)PyArray_DATA(data_out_py);
info = phonopy_pinv(data_out, data_in, m, n, cutoff);
info = phonopy_pinv(data_out, data_in, m, n, cutoff);
return PyLong_FromLong((long)info);
return PyLong_FromLong((long)info);
}

File diff suppressed because it is too large Load Diff

View File

@ -34,14 +34,14 @@
#include <Python.h>
#include <numpy/arrayobject.h>
#include "lapack_wrapper.h"
#include "phononmod.h"
static PyObject *py_get_phonons_at_gridpoints(PyObject *self, PyObject *args);
struct module_state
{
PyObject *error;
struct module_state {
PyObject *error;
};
#if PY_MAJOR_VERSION >= 3
@ -51,52 +51,38 @@ struct module_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 PyObject *error_out(PyObject *m) {
struct module_state *st = GETSTATE(m);
PyErr_SetString(st->error, "something bad happened");
return NULL;
}
static PyMethodDef _phononmod_methods[] = {
{"error_out", (PyCFunction)error_out, METH_NOARGS, NULL},
{"phonons_at_gridpoints",
py_get_phonons_at_gridpoints,
METH_VARARGS,
{"phonons_at_gridpoints", py_get_phonons_at_gridpoints, METH_VARARGS,
"Set phonons at grid points"},
{NULL, NULL, 0, NULL}};
#if PY_MAJOR_VERSION >= 3
static int _phononmod_traverse(PyObject *m, visitproc visit, void *arg)
{
Py_VISIT(GETSTATE(m)->error);
return 0;
static int _phononmod_traverse(PyObject *m, visitproc visit, void *arg) {
Py_VISIT(GETSTATE(m)->error);
return 0;
}
static int _phononmod_clear(PyObject *m)
{
Py_CLEAR(GETSTATE(m)->error);
return 0;
static int _phononmod_clear(PyObject *m) {
Py_CLEAR(GETSTATE(m)->error);
return 0;
}
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_phononmod",
NULL,
sizeof(struct module_state),
_phononmod_methods,
NULL,
_phononmod_traverse,
_phononmod_clear,
NULL};
PyModuleDef_HEAD_INIT, "_phononmod", NULL,
sizeof(struct module_state), _phononmod_methods, NULL,
_phononmod_traverse, _phononmod_clear, NULL};
#define INITERROR return NULL
PyObject *
PyInit__phononmod(void)
PyObject *PyInit__phononmod(void)
#else
#define INITERROR return
@ -104,205 +90,143 @@ void init_phononmod(void)
#endif
{
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create(&moduledef);
PyObject *module = PyModule_Create(&moduledef);
#else
PyObject *module = Py_InitModule("_phononmod", _phononmod_methods);
PyObject *module = Py_InitModule("_phononmod", _phononmod_methods);
#endif
struct module_state *st;
struct module_state *st;
if (module == NULL)
INITERROR;
st = GETSTATE(module);
if (module == NULL) INITERROR;
st = GETSTATE(module);
st->error = PyErr_NewException("_phononmod.Error", NULL, NULL);
if (st->error == NULL)
{
Py_DECREF(module);
INITERROR;
}
st->error = PyErr_NewException("_phononmod.Error", NULL, NULL);
if (st->error == NULL) {
Py_DECREF(module);
INITERROR;
}
#if PY_MAJOR_VERSION >= 3
return module;
return module;
#endif
}
static PyObject *py_get_phonons_at_gridpoints(PyObject *self, PyObject *args)
{
PyArrayObject *py_frequencies;
PyArrayObject *py_eigenvectors;
PyArrayObject *py_phonon_done;
PyArrayObject *py_grid_points;
PyArrayObject *py_grid_address;
PyArrayObject *py_QDinv;
PyArrayObject *py_shortest_vectors_fc2;
PyArrayObject *py_multiplicity_fc2;
PyArrayObject *py_positions_fc2;
PyArrayObject *py_fc2;
PyArrayObject *py_masses_fc2;
PyArrayObject *py_p2s_map_fc2;
PyArrayObject *py_s2p_map_fc2;
PyArrayObject *py_reciprocal_lattice;
PyArrayObject *py_born_effective_charge;
PyArrayObject *py_q_direction;
PyArrayObject *py_dielectric_constant;
PyArrayObject *py_dd_q0;
PyArrayObject *py_G_list;
double nac_factor;
double unit_conversion_factor;
double lambda;
char *uplo;
static PyObject *py_get_phonons_at_gridpoints(PyObject *self, PyObject *args) {
PyArrayObject *py_frequencies;
PyArrayObject *py_eigenvectors;
PyArrayObject *py_phonon_done;
PyArrayObject *py_grid_points;
PyArrayObject *py_grid_address;
PyArrayObject *py_QDinv;
PyArrayObject *py_shortest_vectors_fc2;
PyArrayObject *py_multiplicity_fc2;
PyArrayObject *py_positions_fc2;
PyArrayObject *py_fc2;
PyArrayObject *py_masses_fc2;
PyArrayObject *py_p2s_map_fc2;
PyArrayObject *py_s2p_map_fc2;
PyArrayObject *py_reciprocal_lattice;
PyArrayObject *py_born_effective_charge;
PyArrayObject *py_q_direction;
PyArrayObject *py_dielectric_constant;
PyArrayObject *py_dd_q0;
PyArrayObject *py_G_list;
double nac_factor;
double unit_conversion_factor;
double lambda;
char *uplo;
double(*born)[3][3];
double(*dielectric)[3];
double *q_dir;
double *freqs;
lapack_complex_double *eigvecs;
char *phonon_done;
long *grid_points;
long(*grid_address)[3];
double(*QDinv)[3];
double *fc2;
double(*svecs_fc2)[3];
long(*multi_fc2)[2];
double(*positions_fc2)[3];
double *masses_fc2;
long *p2s_fc2;
long *s2p_fc2;
double(*rec_lat)[3];
double *dd_q0;
double(*G_list)[3];
long num_patom, num_satom, num_phonons, num_grid_points, num_G_points;
double(*born)[3][3];
double(*dielectric)[3];
double *q_dir;
double *freqs;
lapack_complex_double *eigvecs;
char *phonon_done;
long *grid_points;
long(*grid_address)[3];
double(*QDinv)[3];
double *fc2;
double(*svecs_fc2)[3];
long(*multi_fc2)[2];
double(*positions_fc2)[3];
double *masses_fc2;
long *p2s_fc2;
long *s2p_fc2;
double(*rec_lat)[3];
double *dd_q0;
double(*G_list)[3];
long num_patom, num_satom, num_phonons, num_grid_points, num_G_points;
if (!PyArg_ParseTuple(args, "OOOOOOOOOOOOOdOOOOdOOds",
&py_frequencies,
&py_eigenvectors,
&py_phonon_done,
&py_grid_points,
&py_grid_address,
&py_QDinv,
&py_fc2,
&py_shortest_vectors_fc2,
&py_multiplicity_fc2,
&py_positions_fc2,
&py_masses_fc2,
&py_p2s_map_fc2,
&py_s2p_map_fc2,
&unit_conversion_factor,
&py_born_effective_charge,
&py_dielectric_constant,
&py_reciprocal_lattice,
&py_q_direction,
&nac_factor,
&py_dd_q0,
&py_G_list,
&lambda,
&uplo))
{
return NULL;
}
freqs = (double *)PyArray_DATA(py_frequencies);
eigvecs = (lapack_complex_double *)PyArray_DATA(py_eigenvectors);
phonon_done = (char *)PyArray_DATA(py_phonon_done);
grid_points = (long *)PyArray_DATA(py_grid_points);
grid_address = (long(*)[3])PyArray_DATA(py_grid_address);
QDinv = (double(*)[3])PyArray_DATA(py_QDinv);
fc2 = (double *)PyArray_DATA(py_fc2);
svecs_fc2 = (double(*)[3])PyArray_DATA(py_shortest_vectors_fc2);
multi_fc2 = (long(*)[2])PyArray_DATA(py_multiplicity_fc2);
masses_fc2 = (double *)PyArray_DATA(py_masses_fc2);
p2s_fc2 = (long *)PyArray_DATA(py_p2s_map_fc2);
s2p_fc2 = (long *)PyArray_DATA(py_s2p_map_fc2);
rec_lat = (double(*)[3])PyArray_DATA(py_reciprocal_lattice);
num_patom = (long)PyArray_DIMS(py_multiplicity_fc2)[1];
num_satom = (long)PyArray_DIMS(py_multiplicity_fc2)[0];
num_phonons = (long)PyArray_DIMS(py_frequencies)[0];
num_grid_points = (long)PyArray_DIMS(py_grid_points)[0];
if ((PyObject *)py_born_effective_charge == Py_None)
{
born = NULL;
}
else
{
born = (double(*)[3][3])PyArray_DATA(py_born_effective_charge);
}
if ((PyObject *)py_dielectric_constant == Py_None)
{
dielectric = NULL;
}
else
{
dielectric = (double(*)[3])PyArray_DATA(py_dielectric_constant);
}
if ((PyObject *)py_q_direction == Py_None)
{
q_dir = NULL;
}
else
{
q_dir = (double *)PyArray_DATA(py_q_direction);
if (fabs(q_dir[0]) < 1e-10 &&
fabs(q_dir[1]) < 1e-10 &&
fabs(q_dir[2]) < 1e-10)
{
q_dir = NULL;
if (!PyArg_ParseTuple(
args, "OOOOOOOOOOOOOdOOOOdOOds", &py_frequencies, &py_eigenvectors,
&py_phonon_done, &py_grid_points, &py_grid_address, &py_QDinv,
&py_fc2, &py_shortest_vectors_fc2, &py_multiplicity_fc2,
&py_positions_fc2, &py_masses_fc2, &py_p2s_map_fc2, &py_s2p_map_fc2,
&unit_conversion_factor, &py_born_effective_charge,
&py_dielectric_constant, &py_reciprocal_lattice, &py_q_direction,
&nac_factor, &py_dd_q0, &py_G_list, &lambda, &uplo)) {
return NULL;
}
}
if ((PyObject *)py_dd_q0 == Py_None)
{
dd_q0 = NULL;
}
else
{
dd_q0 = (double *)PyArray_DATA(py_dd_q0);
}
if ((PyObject *)py_G_list == Py_None)
{
G_list = NULL;
num_G_points = 0;
}
else
{
G_list = (double(*)[3])PyArray_DATA(py_G_list);
num_G_points = (long)PyArray_DIMS(py_G_list)[0];
}
if ((PyObject *)py_positions_fc2 == Py_None)
{
positions_fc2 = NULL;
}
else
{
positions_fc2 = (double(*)[3])PyArray_DATA(py_positions_fc2);
}
phmod_get_phonons_at_gridpoints(freqs,
eigvecs,
phonon_done,
num_phonons,
grid_points,
num_grid_points,
grid_address,
QDinv,
fc2,
svecs_fc2,
multi_fc2,
positions_fc2,
num_patom,
num_satom,
masses_fc2,
p2s_fc2,
s2p_fc2,
unit_conversion_factor,
born,
dielectric,
rec_lat,
q_dir,
nac_factor,
dd_q0,
G_list,
num_G_points,
lambda,
uplo[0]);
freqs = (double *)PyArray_DATA(py_frequencies);
eigvecs = (lapack_complex_double *)PyArray_DATA(py_eigenvectors);
phonon_done = (char *)PyArray_DATA(py_phonon_done);
grid_points = (long *)PyArray_DATA(py_grid_points);
grid_address = (long(*)[3])PyArray_DATA(py_grid_address);
QDinv = (double(*)[3])PyArray_DATA(py_QDinv);
fc2 = (double *)PyArray_DATA(py_fc2);
svecs_fc2 = (double(*)[3])PyArray_DATA(py_shortest_vectors_fc2);
multi_fc2 = (long(*)[2])PyArray_DATA(py_multiplicity_fc2);
masses_fc2 = (double *)PyArray_DATA(py_masses_fc2);
p2s_fc2 = (long *)PyArray_DATA(py_p2s_map_fc2);
s2p_fc2 = (long *)PyArray_DATA(py_s2p_map_fc2);
rec_lat = (double(*)[3])PyArray_DATA(py_reciprocal_lattice);
num_patom = (long)PyArray_DIMS(py_multiplicity_fc2)[1];
num_satom = (long)PyArray_DIMS(py_multiplicity_fc2)[0];
num_phonons = (long)PyArray_DIMS(py_frequencies)[0];
num_grid_points = (long)PyArray_DIMS(py_grid_points)[0];
if ((PyObject *)py_born_effective_charge == Py_None) {
born = NULL;
} else {
born = (double(*)[3][3])PyArray_DATA(py_born_effective_charge);
}
if ((PyObject *)py_dielectric_constant == Py_None) {
dielectric = NULL;
} else {
dielectric = (double(*)[3])PyArray_DATA(py_dielectric_constant);
}
if ((PyObject *)py_q_direction == Py_None) {
q_dir = NULL;
} else {
q_dir = (double *)PyArray_DATA(py_q_direction);
if (fabs(q_dir[0]) < 1e-10 && fabs(q_dir[1]) < 1e-10 &&
fabs(q_dir[2]) < 1e-10) {
q_dir = NULL;
}
}
if ((PyObject *)py_dd_q0 == Py_None) {
dd_q0 = NULL;
} else {
dd_q0 = (double *)PyArray_DATA(py_dd_q0);
}
if ((PyObject *)py_G_list == Py_None) {
G_list = NULL;
num_G_points = 0;
} else {
G_list = (double(*)[3])PyArray_DATA(py_G_list);
num_G_points = (long)PyArray_DIMS(py_G_list)[0];
}
if ((PyObject *)py_positions_fc2 == Py_None) {
positions_fc2 = NULL;
} else {
positions_fc2 = (double(*)[3])PyArray_DATA(py_positions_fc2);
}
Py_RETURN_NONE;
phmod_get_phonons_at_gridpoints(
freqs, eigvecs, phonon_done, num_phonons, grid_points, num_grid_points,
grid_address, QDinv, fc2, svecs_fc2, multi_fc2, positions_fc2,
num_patom, num_satom, masses_fc2, p2s_fc2, s2p_fc2,
unit_conversion_factor, born, dielectric, rec_lat, q_dir, nac_factor,
dd_q0, G_list, num_G_points, lambda, uplo[0]);
Py_RETURN_NONE;
}

View File

@ -32,555 +32,373 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include "bzgrid.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include "bzgrid.h"
#include "grgrid.h"
#include "lagrid.h"
#define BZG_NUM_BZ_SEARCH_SPACE 125
#define GRID_TOLERANCE_FACTOR 0.01
static long bz_search_space[BZG_NUM_BZ_SEARCH_SPACE][3] = {
{0, 0, 0},
{0, 0, 1},
{0, 0, 2},
{0, 0, -2},
{0, 0, -1},
{0, 1, 0},
{0, 1, 1},
{0, 1, 2},
{0, 1, -2},
{0, 1, -1},
{0, 2, 0},
{0, 2, 1},
{0, 2, 2},
{0, 2, -2},
{0, 2, -1},
{0, -2, 0},
{0, -2, 1},
{0, -2, 2},
{0, -2, -2},
{0, -2, -1},
{0, -1, 0},
{0, -1, 1},
{0, -1, 2},
{0, -1, -2},
{0, -1, -1},
{1, 0, 0},
{1, 0, 1},
{1, 0, 2},
{1, 0, -2},
{1, 0, -1},
{1, 1, 0},
{1, 1, 1},
{1, 1, 2},
{1, 1, -2},
{1, 1, -1},
{1, 2, 0},
{1, 2, 1},
{1, 2, 2},
{1, 2, -2},
{1, 2, -1},
{1, -2, 0},
{1, -2, 1},
{1, -2, 2},
{1, -2, -2},
{1, -2, -1},
{1, -1, 0},
{1, -1, 1},
{1, -1, 2},
{1, -1, -2},
{1, -1, -1},
{2, 0, 0},
{2, 0, 1},
{2, 0, 2},
{2, 0, -2},
{2, 0, -1},
{2, 1, 0},
{2, 1, 1},
{2, 1, 2},
{2, 1, -2},
{2, 1, -1},
{2, 2, 0},
{2, 2, 1},
{2, 2, 2},
{2, 2, -2},
{2, 2, -1},
{2, -2, 0},
{2, -2, 1},
{2, -2, 2},
{2, -2, -2},
{2, -2, -1},
{2, -1, 0},
{2, -1, 1},
{2, -1, 2},
{2, -1, -2},
{2, -1, -1},
{-2, 0, 0},
{-2, 0, 1},
{-2, 0, 2},
{-2, 0, -2},
{-2, 0, -1},
{-2, 1, 0},
{-2, 1, 1},
{-2, 1, 2},
{-2, 1, -2},
{-2, 1, -1},
{-2, 2, 0},
{-2, 2, 1},
{-2, 2, 2},
{-2, 2, -2},
{-2, 2, -1},
{-2, -2, 0},
{-2, -2, 1},
{-2, -2, 2},
{-2, -2, -2},
{-2, -2, -1},
{-2, -1, 0},
{-2, -1, 1},
{-2, -1, 2},
{-2, -1, -2},
{-2, -1, -1},
{-1, 0, 0},
{-1, 0, 1},
{-1, 0, 2},
{-1, 0, -2},
{-1, 0, -1},
{-1, 1, 0},
{-1, 1, 1},
{-1, 1, 2},
{-1, 1, -2},
{-1, 1, -1},
{-1, 2, 0},
{-1, 2, 1},
{-1, 2, 2},
{-1, 2, -2},
{-1, 2, -1},
{-1, -2, 0},
{-1, -2, 1},
{-1, -2, 2},
{-1, -2, -2},
{-1, -2, -1},
{-1, -1, 0},
{-1, -1, 1},
{-1, -1, 2},
{-1, -1, -2},
{-1, -1, -1}};
{0, 0, 0}, {0, 0, 1}, {0, 0, 2}, {0, 0, -2}, {0, 0, -1},
{0, 1, 0}, {0, 1, 1}, {0, 1, 2}, {0, 1, -2}, {0, 1, -1},
{0, 2, 0}, {0, 2, 1}, {0, 2, 2}, {0, 2, -2}, {0, 2, -1},
{0, -2, 0}, {0, -2, 1}, {0, -2, 2}, {0, -2, -2}, {0, -2, -1},
{0, -1, 0}, {0, -1, 1}, {0, -1, 2}, {0, -1, -2}, {0, -1, -1},
{1, 0, 0}, {1, 0, 1}, {1, 0, 2}, {1, 0, -2}, {1, 0, -1},
{1, 1, 0}, {1, 1, 1}, {1, 1, 2}, {1, 1, -2}, {1, 1, -1},
{1, 2, 0}, {1, 2, 1}, {1, 2, 2}, {1, 2, -2}, {1, 2, -1},
{1, -2, 0}, {1, -2, 1}, {1, -2, 2}, {1, -2, -2}, {1, -2, -1},
{1, -1, 0}, {1, -1, 1}, {1, -1, 2}, {1, -1, -2}, {1, -1, -1},
{2, 0, 0}, {2, 0, 1}, {2, 0, 2}, {2, 0, -2}, {2, 0, -1},
{2, 1, 0}, {2, 1, 1}, {2, 1, 2}, {2, 1, -2}, {2, 1, -1},
{2, 2, 0}, {2, 2, 1}, {2, 2, 2}, {2, 2, -2}, {2, 2, -1},
{2, -2, 0}, {2, -2, 1}, {2, -2, 2}, {2, -2, -2}, {2, -2, -1},
{2, -1, 0}, {2, -1, 1}, {2, -1, 2}, {2, -1, -2}, {2, -1, -1},
{-2, 0, 0}, {-2, 0, 1}, {-2, 0, 2}, {-2, 0, -2}, {-2, 0, -1},
{-2, 1, 0}, {-2, 1, 1}, {-2, 1, 2}, {-2, 1, -2}, {-2, 1, -1},
{-2, 2, 0}, {-2, 2, 1}, {-2, 2, 2}, {-2, 2, -2}, {-2, 2, -1},
{-2, -2, 0}, {-2, -2, 1}, {-2, -2, 2}, {-2, -2, -2}, {-2, -2, -1},
{-2, -1, 0}, {-2, -1, 1}, {-2, -1, 2}, {-2, -1, -2}, {-2, -1, -1},
{-1, 0, 0}, {-1, 0, 1}, {-1, 0, 2}, {-1, 0, -2}, {-1, 0, -1},
{-1, 1, 0}, {-1, 1, 1}, {-1, 1, 2}, {-1, 1, -2}, {-1, 1, -1},
{-1, 2, 0}, {-1, 2, 1}, {-1, 2, 2}, {-1, 2, -2}, {-1, 2, -1},
{-1, -2, 0}, {-1, -2, 1}, {-1, -2, 2}, {-1, -2, -2}, {-1, -2, -1},
{-1, -1, 0}, {-1, -1, 1}, {-1, -1, 2}, {-1, -1, -2}, {-1, -1, -1}};
static void get_bz_grid_addresses_type1(BZGrid *bzgrid,
const long Qinv[3][3]);
static void get_bz_grid_addresses_type2(BZGrid *bzgrid,
const long Qinv[3][3]);
static void set_bz_address(long address[3],
const long bz_index,
const long grid_address[3],
const long D_diag[3],
const long nint[3],
const long Qinv[3][3]);
static double get_bz_distances(long nint[3],
double distances[],
const BZGrid *bzgrid,
const long grid_address[3],
static void get_bz_grid_addresses_type1(BZGrid *bzgrid, const long Qinv[3][3]);
static void get_bz_grid_addresses_type2(BZGrid *bzgrid, const long Qinv[3][3]);
static void set_bz_address(long address[3], const long bz_index,
const long grid_address[3], const long D_diag[3],
const long nint[3], const long Qinv[3][3]);
static double get_bz_distances(long nint[3], double distances[],
const BZGrid *bzgrid, const long grid_address[3],
const double tolerance);
static void multiply_matrix_vector_d3(double v[3],
const double a[3][3],
static void multiply_matrix_vector_d3(double v[3], const double a[3][3],
const double b[3]);
static long get_inverse_unimodular_matrix_l3(long m[3][3],
const long a[3][3]);
static long get_inverse_unimodular_matrix_l3(long m[3][3], const long a[3][3]);
static double norm_squared_d3(const double a[3]);
long bzg_rotate_grid_index(const long bz_grid_index,
const long rotation[3][3],
const ConstBZGrid *bzgrid)
{
long i, gp, num_bzgp, num_grgp;
long dadrs[3], dadrs_rot[3], adrs_rot[3];
long bzg_rotate_grid_index(const long bz_grid_index, const long rotation[3][3],
const ConstBZGrid *bzgrid) {
long i, gp, num_bzgp, num_grgp;
long dadrs[3], dadrs_rot[3], adrs_rot[3];
grg_get_double_grid_address(dadrs, bzgrid->addresses[bz_grid_index], bzgrid->PS);
lagmat_multiply_matrix_vector_l3(dadrs_rot, rotation, dadrs);
grg_get_grid_address(adrs_rot, dadrs_rot, bzgrid->PS);
gp = grg_get_grid_index(adrs_rot, bzgrid->D_diag);
grg_get_double_grid_address(dadrs, bzgrid->addresses[bz_grid_index],
bzgrid->PS);
lagmat_multiply_matrix_vector_l3(dadrs_rot, rotation, dadrs);
grg_get_grid_address(adrs_rot, dadrs_rot, bzgrid->PS);
gp = grg_get_grid_index(adrs_rot, bzgrid->D_diag);
if (bzgrid->type == 1)
{
if (bzgrid->addresses[gp][0] == adrs_rot[0] &&
bzgrid->addresses[gp][1] == adrs_rot[1] &&
bzgrid->addresses[gp][2] == adrs_rot[2])
{
return gp;
if (bzgrid->type == 1) {
if (bzgrid->addresses[gp][0] == adrs_rot[0] &&
bzgrid->addresses[gp][1] == adrs_rot[1] &&
bzgrid->addresses[gp][2] == adrs_rot[2]) {
return gp;
}
num_grgp = bzgrid->D_diag[0] * bzgrid->D_diag[1] * bzgrid->D_diag[2];
num_bzgp = num_grgp * 8;
for (i = bzgrid->gp_map[num_bzgp + gp] + num_grgp;
i < bzgrid->gp_map[num_bzgp + gp + 1] + num_grgp; i++) {
if (bzgrid->addresses[i][0] == adrs_rot[0] &&
bzgrid->addresses[i][1] == adrs_rot[1] &&
bzgrid->addresses[i][2] == adrs_rot[2]) {
return i;
}
}
} else {
for (i = bzgrid->gp_map[gp]; i < bzgrid->gp_map[gp + 1]; i++) {
if (bzgrid->addresses[i][0] == adrs_rot[0] &&
bzgrid->addresses[i][1] == adrs_rot[1] &&
bzgrid->addresses[i][2] == adrs_rot[2]) {
return i;
}
}
}
num_grgp = bzgrid->D_diag[0] * bzgrid->D_diag[1] * bzgrid->D_diag[2];
num_bzgp = num_grgp * 8;
for (i = bzgrid->gp_map[num_bzgp + gp] + num_grgp;
i < bzgrid->gp_map[num_bzgp + gp + 1] + num_grgp; i++)
{
if (bzgrid->addresses[i][0] == adrs_rot[0] &&
bzgrid->addresses[i][1] == adrs_rot[1] &&
bzgrid->addresses[i][2] == adrs_rot[2])
{
return i;
}
}
}
else
{
for (i = bzgrid->gp_map[gp]; i < bzgrid->gp_map[gp + 1]; i++)
{
if (bzgrid->addresses[i][0] == adrs_rot[0] &&
bzgrid->addresses[i][1] == adrs_rot[1] &&
bzgrid->addresses[i][2] == adrs_rot[2])
{
return i;
}
}
}
/* This should not happen, but possible when bzgrid is ill-defined. */
return bzgrid->gp_map[gp];
/* This should not happen, but possible when bzgrid is ill-defined. */
return bzgrid->gp_map[gp];
}
long bzg_get_bz_grid_addresses(BZGrid *bzgrid)
{
long det;
long Qinv[3][3];
long bzg_get_bz_grid_addresses(BZGrid *bzgrid) {
long det;
long Qinv[3][3];
det = get_inverse_unimodular_matrix_l3(Qinv, bzgrid->Q);
if (det == 0)
{
return 0;
}
det = get_inverse_unimodular_matrix_l3(Qinv, bzgrid->Q);
if (det == 0) {
return 0;
}
if (bzgrid->type == 1)
{
get_bz_grid_addresses_type1(bzgrid, Qinv);
}
else
{
get_bz_grid_addresses_type2(bzgrid, Qinv);
}
if (bzgrid->type == 1) {
get_bz_grid_addresses_type1(bzgrid, Qinv);
} else {
get_bz_grid_addresses_type2(bzgrid, Qinv);
}
return 1;
return 1;
}
/* Note: Tolerance in squared distance. */
double bzg_get_tolerance_for_BZ_reduction(const BZGrid *bzgrid)
{
long i, j;
double tolerance;
double length[3];
double reclatQ[3][3];
double bzg_get_tolerance_for_BZ_reduction(const BZGrid *bzgrid) {
long i, j;
double tolerance;
double length[3];
double reclatQ[3][3];
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
reclatQ[i][j] =
bzgrid->reclat[i][0] * bzgrid->Q[0][j] + bzgrid->reclat[i][1] * bzgrid->Q[1][j] + bzgrid->reclat[i][2] * bzgrid->Q[2][j];
}
}
for (i = 0; i < 3; i++)
{
length[i] = 0;
for (j = 0; j < 3; j++)
{
length[i] += reclatQ[j][i] * reclatQ[j][i];
}
length[i] /= bzgrid->D_diag[i] * bzgrid->D_diag[i];
}
tolerance = length[0];
for (i = 1; i < 3; i++)
{
if (tolerance < length[i])
{
tolerance = length[i];
}
}
tolerance *= GRID_TOLERANCE_FACTOR;
return tolerance;
}
RotMats *bzg_alloc_RotMats(const long size)
{
RotMats *rotmats;
rotmats = NULL;
if ((rotmats = (RotMats *)malloc(sizeof(RotMats))) == NULL)
{
warning_print("Memory could not be allocated.");
return NULL;
}
rotmats->size = size;
if (size > 0)
{
if ((rotmats->mat = (long(*)[3][3])malloc(sizeof(long[3][3]) * size)) == NULL)
{
warning_print("Memory could not be allocated ");
warning_print("(RotMats, line %d, %s).\n", __LINE__, __FILE__);
free(rotmats);
rotmats = NULL;
return NULL;
}
}
return rotmats;
}
void bzg_free_RotMats(RotMats *rotmats)
{
if (rotmats->size > 0)
{
free(rotmats->mat);
rotmats->mat = NULL;
}
free(rotmats);
}
void bzg_multiply_matrix_vector_ld3(double v[3],
const long a[3][3],
const double b[3])
{
long i;
double c[3];
for (i = 0; i < 3; i++)
{
c[i] = a[i][0] * b[0] + a[i][1] * b[1] + a[i][2] * b[2];
}
for (i = 0; i < 3; i++)
{
v[i] = c[i];
}
}
static void get_bz_grid_addresses_type1(BZGrid *bzgrid,
const long Qinv[3][3])
{
double tolerance, min_distance;
double distances[BZG_NUM_BZ_SEARCH_SPACE];
long bzmesh[3], bz_address_double[3], nint[3], gr_adrs[3];
long i, j, k, boundary_num_gp, total_num_gp, bzgp, gp, num_bzmesh;
long count, id_shift;
tolerance = bzg_get_tolerance_for_BZ_reduction(bzgrid);
for (j = 0; j < 3; j++)
{
bzmesh[j] = bzgrid->D_diag[j] * 2;
}
num_bzmesh = bzmesh[0] * bzmesh[1] * bzmesh[2];
for (i = 0; i < num_bzmesh; i++)
{
bzgrid->gp_map[i] = num_bzmesh;
}
boundary_num_gp = 0;
total_num_gp = bzgrid->D_diag[0] * bzgrid->D_diag[1] * bzgrid->D_diag[2];
/* Multithreading doesn't work for this loop since gp calculated */
/* with boundary_num_gp is unstable to store bz_grid_address. */
bzgrid->gp_map[num_bzmesh] = 0;
id_shift = 0;
for (i = 0; i < total_num_gp; i++)
{
grg_get_grid_address_from_index(gr_adrs, i, bzgrid->D_diag);
min_distance = get_bz_distances(nint, distances, bzgrid,
gr_adrs, tolerance);
count = 0;
for (j = 0; j < BZG_NUM_BZ_SEARCH_SPACE; j++)
{
if (distances[j] < min_distance + tolerance)
{
if (count == 0)
{
gp = i;
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
reclatQ[i][j] = bzgrid->reclat[i][0] * bzgrid->Q[0][j] +
bzgrid->reclat[i][1] * bzgrid->Q[1][j] +
bzgrid->reclat[i][2] * bzgrid->Q[2][j];
}
else
{
gp = boundary_num_gp + total_num_gp;
boundary_num_gp++;
}
for (i = 0; i < 3; i++) {
length[i] = 0;
for (j = 0; j < 3; j++) {
length[i] += reclatQ[j][i] * reclatQ[j][i];
}
count++;
set_bz_address(bzgrid->addresses[gp],
j,
gr_adrs,
bzgrid->D_diag,
nint,
Qinv);
for (k = 0; k < 3; k++)
{
bz_address_double[k] = bzgrid->addresses[gp][k] * 2 + bzgrid->PS[k];
length[i] /= bzgrid->D_diag[i] * bzgrid->D_diag[i];
}
tolerance = length[0];
for (i = 1; i < 3; i++) {
if (tolerance < length[i]) {
tolerance = length[i];
}
bzgp = grg_get_double_grid_index(
bz_address_double, bzmesh, bzgrid->PS);
bzgrid->gp_map[bzgp] = gp;
bzgrid->bzg2grg[gp] = i;
}
}
/* This is used in get_BZ_triplets_at_q_type1. */
/* The first one among those found is treated specially, so */
/* excluded from the gp_map address shift by -1. */
id_shift += count - 1;
bzgrid->gp_map[num_bzmesh + i + 1] = id_shift;
}
bzgrid->size = boundary_num_gp + total_num_gp;
tolerance *= GRID_TOLERANCE_FACTOR;
return tolerance;
}
static void get_bz_grid_addresses_type2(BZGrid *bzgrid,
const long Qinv[3][3])
{
double tolerance, min_distance;
double distances[BZG_NUM_BZ_SEARCH_SPACE];
long nint[3], gr_adrs[3];
long i, j, num_gp;
RotMats *bzg_alloc_RotMats(const long size) {
RotMats *rotmats;
tolerance = bzg_get_tolerance_for_BZ_reduction(bzgrid);
num_gp = 0;
/* The first element of gp_map is always 0. */
bzgrid->gp_map[0] = 0;
rotmats = NULL;
for (i = 0;
i < bzgrid->D_diag[0] * bzgrid->D_diag[1] * bzgrid->D_diag[2]; i++)
{
grg_get_grid_address_from_index(gr_adrs, i, bzgrid->D_diag);
min_distance = get_bz_distances(nint, distances, bzgrid,
gr_adrs, tolerance);
for (j = 0; j < BZG_NUM_BZ_SEARCH_SPACE; j++)
{
if (distances[j] < min_distance + tolerance)
{
set_bz_address(bzgrid->addresses[num_gp],
j,
gr_adrs,
bzgrid->D_diag,
nint,
Qinv);
bzgrid->bzg2grg[num_gp] = i;
num_gp++;
}
if ((rotmats = (RotMats *)malloc(sizeof(RotMats))) == NULL) {
warning_print("Memory could not be allocated.");
return NULL;
}
bzgrid->gp_map[i + 1] = num_gp;
}
bzgrid->size = num_gp;
}
static void set_bz_address(long address[3],
const long bz_index,
const long grid_address[3],
const long D_diag[3],
const long nint[3],
const long Qinv[3][3])
{
long i;
long deltaG[3];
for (i = 0; i < 3; i++)
{
deltaG[i] = bz_search_space[bz_index][i] - nint[i];
}
lagmat_multiply_matrix_vector_l3(deltaG, Qinv, deltaG);
for (i = 0; i < 3; i++)
{
address[i] = grid_address[i] + deltaG[i] * D_diag[i];
}
}
static double get_bz_distances(long nint[3],
double distances[],
const BZGrid *bzgrid,
const long grid_address[3],
const double tolerance)
{
long i, j;
long dadrs[3];
double min_distance;
double q_vec[3], q_red[3];
grg_get_double_grid_address(dadrs, grid_address, bzgrid->PS);
for (i = 0; i < 3; i++)
{
q_red[i] = dadrs[i] / (2.0 * bzgrid->D_diag[i]);
}
bzg_multiply_matrix_vector_ld3(q_red, bzgrid->Q, q_red);
for (i = 0; i < 3; i++)
{
nint[i] = lagmat_Nint(q_red[i]);
q_red[i] -= nint[i];
}
for (i = 0; i < BZG_NUM_BZ_SEARCH_SPACE; i++)
{
for (j = 0; j < 3; j++)
{
q_vec[j] = q_red[j] + bz_search_space[i][j];
rotmats->size = size;
if (size > 0) {
if ((rotmats->mat = (long(*)[3][3])malloc(sizeof(long[3][3]) * size)) ==
NULL) {
warning_print("Memory could not be allocated ");
warning_print("(RotMats, line %d, %s).\n", __LINE__, __FILE__);
free(rotmats);
rotmats = NULL;
return NULL;
}
}
multiply_matrix_vector_d3(q_vec, bzgrid->reclat, q_vec);
distances[i] = norm_squared_d3(q_vec);
}
return rotmats;
}
/* Use of tolerance is important to select first one among similar
* distances. Otherwise the choice of bz grid address among
* those translationally equivalent can change by very tiny numerical
* fluctuation. */
min_distance = distances[0];
for (i = 1; i < BZG_NUM_BZ_SEARCH_SPACE; i++)
{
if (distances[i] < min_distance - tolerance)
{
min_distance = distances[i];
void bzg_free_RotMats(RotMats *rotmats) {
if (rotmats->size > 0) {
free(rotmats->mat);
rotmats->mat = NULL;
}
}
return min_distance;
free(rotmats);
}
static void multiply_matrix_vector_d3(double v[3],
const double a[3][3],
const double b[3])
{
long i;
double c[3];
for (i = 0; i < 3; i++)
{
c[i] = a[i][0] * b[0] + a[i][1] * b[1] + a[i][2] * b[2];
}
for (i = 0; i < 3; i++)
{
v[i] = c[i];
}
void bzg_multiply_matrix_vector_ld3(double v[3], const long a[3][3],
const double b[3]) {
long i;
double c[3];
for (i = 0; i < 3; i++) {
c[i] = a[i][0] * b[0] + a[i][1] * b[1] + a[i][2] * b[2];
}
for (i = 0; i < 3; i++) {
v[i] = c[i];
}
}
static long get_inverse_unimodular_matrix_l3(long m[3][3],
const long a[3][3])
{
long det;
long c[3][3];
static void get_bz_grid_addresses_type1(BZGrid *bzgrid, const long Qinv[3][3]) {
double tolerance, min_distance;
double distances[BZG_NUM_BZ_SEARCH_SPACE];
long bzmesh[3], bz_address_double[3], nint[3], gr_adrs[3];
long i, j, k, boundary_num_gp, total_num_gp, bzgp, gp, num_bzmesh;
long count, id_shift;
det = lagmat_get_determinant_l3(a);
if (labs(det) != 1)
{
return 0;
}
tolerance = bzg_get_tolerance_for_BZ_reduction(bzgrid);
for (j = 0; j < 3; j++) {
bzmesh[j] = bzgrid->D_diag[j] * 2;
}
c[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det;
c[1][0] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) / det;
c[2][0] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det;
c[0][1] = (a[2][1] * a[0][2] - a[2][2] * a[0][1]) / det;
c[1][1] = (a[2][2] * a[0][0] - a[2][0] * a[0][2]) / det;
c[2][1] = (a[2][0] * a[0][1] - a[2][1] * a[0][0]) / det;
c[0][2] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det;
c[1][2] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) / det;
c[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det;
lagmat_copy_matrix_l3(m, c);
num_bzmesh = bzmesh[0] * bzmesh[1] * bzmesh[2];
for (i = 0; i < num_bzmesh; i++) {
bzgrid->gp_map[i] = num_bzmesh;
}
return det;
boundary_num_gp = 0;
total_num_gp = bzgrid->D_diag[0] * bzgrid->D_diag[1] * bzgrid->D_diag[2];
/* Multithreading doesn't work for this loop since gp calculated */
/* with boundary_num_gp is unstable to store bz_grid_address. */
bzgrid->gp_map[num_bzmesh] = 0;
id_shift = 0;
for (i = 0; i < total_num_gp; i++) {
grg_get_grid_address_from_index(gr_adrs, i, bzgrid->D_diag);
min_distance =
get_bz_distances(nint, distances, bzgrid, gr_adrs, tolerance);
count = 0;
for (j = 0; j < BZG_NUM_BZ_SEARCH_SPACE; j++) {
if (distances[j] < min_distance + tolerance) {
if (count == 0) {
gp = i;
} else {
gp = boundary_num_gp + total_num_gp;
boundary_num_gp++;
}
count++;
set_bz_address(bzgrid->addresses[gp], j, gr_adrs,
bzgrid->D_diag, nint, Qinv);
for (k = 0; k < 3; k++) {
bz_address_double[k] =
bzgrid->addresses[gp][k] * 2 + bzgrid->PS[k];
}
bzgp = grg_get_double_grid_index(bz_address_double, bzmesh,
bzgrid->PS);
bzgrid->gp_map[bzgp] = gp;
bzgrid->bzg2grg[gp] = i;
}
}
/* This is used in get_BZ_triplets_at_q_type1. */
/* The first one among those found is treated specially, so */
/* excluded from the gp_map address shift by -1. */
id_shift += count - 1;
bzgrid->gp_map[num_bzmesh + i + 1] = id_shift;
}
bzgrid->size = boundary_num_gp + total_num_gp;
}
static double norm_squared_d3(const double a[3])
{
return a[0] * a[0] + a[1] * a[1] + a[2] * a[2];
static void get_bz_grid_addresses_type2(BZGrid *bzgrid, const long Qinv[3][3]) {
double tolerance, min_distance;
double distances[BZG_NUM_BZ_SEARCH_SPACE];
long nint[3], gr_adrs[3];
long i, j, num_gp;
tolerance = bzg_get_tolerance_for_BZ_reduction(bzgrid);
num_gp = 0;
/* The first element of gp_map is always 0. */
bzgrid->gp_map[0] = 0;
for (i = 0; i < bzgrid->D_diag[0] * bzgrid->D_diag[1] * bzgrid->D_diag[2];
i++) {
grg_get_grid_address_from_index(gr_adrs, i, bzgrid->D_diag);
min_distance =
get_bz_distances(nint, distances, bzgrid, gr_adrs, tolerance);
for (j = 0; j < BZG_NUM_BZ_SEARCH_SPACE; j++) {
if (distances[j] < min_distance + tolerance) {
set_bz_address(bzgrid->addresses[num_gp], j, gr_adrs,
bzgrid->D_diag, nint, Qinv);
bzgrid->bzg2grg[num_gp] = i;
num_gp++;
}
}
bzgrid->gp_map[i + 1] = num_gp;
}
bzgrid->size = num_gp;
}
static void set_bz_address(long address[3], const long bz_index,
const long grid_address[3], const long D_diag[3],
const long nint[3], const long Qinv[3][3]) {
long i;
long deltaG[3];
for (i = 0; i < 3; i++) {
deltaG[i] = bz_search_space[bz_index][i] - nint[i];
}
lagmat_multiply_matrix_vector_l3(deltaG, Qinv, deltaG);
for (i = 0; i < 3; i++) {
address[i] = grid_address[i] + deltaG[i] * D_diag[i];
}
}
static double get_bz_distances(long nint[3], double distances[],
const BZGrid *bzgrid, const long grid_address[3],
const double tolerance) {
long i, j;
long dadrs[3];
double min_distance;
double q_vec[3], q_red[3];
grg_get_double_grid_address(dadrs, grid_address, bzgrid->PS);
for (i = 0; i < 3; i++) {
q_red[i] = dadrs[i] / (2.0 * bzgrid->D_diag[i]);
}
bzg_multiply_matrix_vector_ld3(q_red, bzgrid->Q, q_red);
for (i = 0; i < 3; i++) {
nint[i] = lagmat_Nint(q_red[i]);
q_red[i] -= nint[i];
}
for (i = 0; i < BZG_NUM_BZ_SEARCH_SPACE; i++) {
for (j = 0; j < 3; j++) {
q_vec[j] = q_red[j] + bz_search_space[i][j];
}
multiply_matrix_vector_d3(q_vec, bzgrid->reclat, q_vec);
distances[i] = norm_squared_d3(q_vec);
}
/* Use of tolerance is important to select first one among similar
* distances. Otherwise the choice of bz grid address among
* those translationally equivalent can change by very tiny numerical
* fluctuation. */
min_distance = distances[0];
for (i = 1; i < BZG_NUM_BZ_SEARCH_SPACE; i++) {
if (distances[i] < min_distance - tolerance) {
min_distance = distances[i];
}
}
return min_distance;
}
static void multiply_matrix_vector_d3(double v[3], const double a[3][3],
const double b[3]) {
long i;
double c[3];
for (i = 0; i < 3; i++) {
c[i] = a[i][0] * b[0] + a[i][1] * b[1] + a[i][2] * b[2];
}
for (i = 0; i < 3; i++) {
v[i] = c[i];
}
}
static long get_inverse_unimodular_matrix_l3(long m[3][3], const long a[3][3]) {
long det;
long c[3][3];
det = lagmat_get_determinant_l3(a);
if (labs(det) != 1) {
return 0;
}
c[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det;
c[1][0] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) / det;
c[2][0] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det;
c[0][1] = (a[2][1] * a[0][2] - a[2][2] * a[0][1]) / det;
c[1][1] = (a[2][2] * a[0][0] - a[2][0] * a[0][2]) / det;
c[2][1] = (a[2][0] * a[0][1] - a[2][1] * a[0][0]) / det;
c[0][2] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det;
c[1][2] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) / det;
c[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det;
lagmat_copy_matrix_l3(m, c);
return det;
}
static double norm_squared_d3(const double a[3]) {
return a[0] * a[0] + a[1] * a[1] + a[2] * a[2];
}

View File

@ -35,10 +35,9 @@
#ifndef __bzgrid_H__
#define __bzgrid_H__
typedef struct
{
long size;
long (*mat)[3][3];
typedef struct {
long size;
long (*mat)[3][3];
} RotMats;
/* Data structure of Brillouin zone grid
@ -68,41 +67,37 @@ typedef struct
* shape=(3, 3)
* type : long
* 1 or 2. */
typedef struct
{
long size;
long D_diag[3];
long Q[3][3];
long PS[3];
long *gp_map;
long *bzg2grg;
long (*addresses)[3];
double reclat[3][3];
long type;
typedef struct {
long size;
long D_diag[3];
long Q[3][3];
long PS[3];
long *gp_map;
long *bzg2grg;
long (*addresses)[3];
double reclat[3][3];
long type;
} BZGrid;
typedef struct
{
long size;
long D_diag[3];
long Q[3][3];
long PS[3];
const long *gp_map;
const long *bzg2grg;
const long (*addresses)[3];
double reclat[3][3];
long type;
typedef struct {
long size;
long D_diag[3];
long Q[3][3];
long PS[3];
const long *gp_map;
const long *bzg2grg;
const long (*addresses)[3];
double reclat[3][3];
long type;
} ConstBZGrid;
long bzg_rotate_grid_index(const long grid_index,
const long rotation[3][3],
long bzg_rotate_grid_index(const long grid_index, const long rotation[3][3],
const ConstBZGrid *bzgrid);
long bzg_get_bz_grid_addresses(BZGrid *bzgrid);
double bzg_get_tolerance_for_BZ_reduction(const BZGrid *bzgrid);
RotMats *bzg_alloc_RotMats(const long size);
void bzg_free_RotMats(RotMats *rotmats);
void bzg_multiply_matrix_vector_ld3(double v[3],
const long a[3][3],
void bzg_multiply_matrix_vector_ld3(double v[3], const long a[3][3],
const double b[3]);
#endif

View File

@ -32,343 +32,255 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "phonoc_array.h"
#include "phonoc_utils.h"
#include "collision_matrix.h"
static void get_collision_matrix(double *collision_matrix,
const double *fc3_normal_squared,
const long num_band0,
const long num_band,
const double *frequencies,
const long (*triplets)[3],
const long *triplets_map,
const long num_gp,
const long *map_q,
const long *rot_grid_points,
const long num_ir_gp,
const long num_rot,
const double *rotations_cartesian,
const double *g,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency);
static void
get_reducible_collision_matrix(double *collision_matrix,
const double *fc3_normal_squared,
const long num_band0,
const long num_band,
const double *frequencies,
const long (*triplets)[3],
const long *triplets_map,
const long num_gp,
const long *map_q,
const double *g,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency);
static void get_inv_sinh(double *inv_sinh,
const long gp,
const double temperature,
const double *frequencies,
const long triplet[3],
const long *triplets_map,
const long *map_q,
const long num_band,
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "phonoc_array.h"
#include "phonoc_utils.h"
static void get_collision_matrix(
double *collision_matrix, const double *fc3_normal_squared,
const long num_band0, const long num_band, const double *frequencies,
const long (*triplets)[3], const long *triplets_map, const long num_gp,
const long *map_q, const long *rot_grid_points, const long num_ir_gp,
const long num_rot, const double *rotations_cartesian, const double *g,
const double temperature, const double unit_conversion_factor,
const double cutoff_frequency);
static void get_reducible_collision_matrix(
double *collision_matrix, const double *fc3_normal_squared,
const long num_band0, const long num_band, const double *frequencies,
const long (*triplets)[3], const long *triplets_map, const long num_gp,
const long *map_q, const double *g, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency);
static long get_inv_sinh(double *inv_sinh, const long gp,
const double temperature, const double *frequencies,
const long triplet[3], const long *triplets_map,
const long *map_q, const long num_band,
const double cutoff_frequency);
static long *create_gp2tp_map(const long *triplets_map,
const long num_gp);
static long *create_gp2tp_map(const long *triplets_map, const long num_gp);
void col_get_collision_matrix(double *collision_matrix,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplets_map,
const long *map_q,
const long *rot_grid_points,
const double *rotations_cartesian,
const double *g,
const long num_ir_gp,
const long num_gp,
const long num_rot,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency)
{
long num_triplets, num_band0, num_band;
void col_get_collision_matrix(
double *collision_matrix, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplets_map, const long *map_q, const long *rot_grid_points,
const double *rotations_cartesian, const double *g, const long num_ir_gp,
const long num_gp, const long num_rot, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency) {
long num_triplets, num_band0, num_band;
num_triplets = fc3_normal_squared->dims[0];
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
num_triplets = fc3_normal_squared->dims[0];
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
get_collision_matrix(
collision_matrix,
fc3_normal_squared->data,
num_band0,
num_band,
frequencies,
triplets,
triplets_map,
num_gp,
map_q,
rot_grid_points,
num_ir_gp,
num_rot,
rotations_cartesian,
g + 2 * num_triplets * num_band0 * num_band * num_band,
temperature,
unit_conversion_factor,
cutoff_frequency);
get_collision_matrix(collision_matrix, fc3_normal_squared->data, num_band0,
num_band, frequencies, triplets, triplets_map, num_gp,
map_q, rot_grid_points, num_ir_gp, num_rot,
rotations_cartesian,
g + 2 * num_triplets * num_band0 * num_band * num_band,
temperature, unit_conversion_factor, cutoff_frequency);
}
void col_get_reducible_collision_matrix(double *collision_matrix,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplets_map,
const long *map_q,
const double *g,
const long num_gp,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency)
{
long num_triplets, num_band, num_band0;
void col_get_reducible_collision_matrix(
double *collision_matrix, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplets_map, const long *map_q, const double *g,
const long num_gp, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency) {
long num_triplets, num_band, num_band0;
num_triplets = fc3_normal_squared->dims[0];
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
num_triplets = fc3_normal_squared->dims[0];
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
get_reducible_collision_matrix(
collision_matrix,
fc3_normal_squared->data,
num_band0,
num_band,
frequencies,
triplets,
triplets_map,
num_gp,
map_q,
g + 2 * num_triplets * num_band0 * num_band * num_band,
temperature,
unit_conversion_factor,
cutoff_frequency);
get_reducible_collision_matrix(
collision_matrix, fc3_normal_squared->data, num_band0, num_band,
frequencies, triplets, triplets_map, num_gp, map_q,
g + 2 * num_triplets * num_band0 * num_band * num_band, temperature,
unit_conversion_factor, cutoff_frequency);
}
static void get_collision_matrix(double *collision_matrix,
const double *fc3_normal_squared,
const long num_band0,
const long num_band,
const double *frequencies,
const long (*triplets)[3],
const long *triplets_map,
const long num_gp,
const long *map_q,
const long *rot_grid_points,
const long num_ir_gp,
const long num_rot,
const double *rotations_cartesian,
const double *g,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency)
{
long i, j, k, l, m, n, ti, r_gp;
long *gp2tp_map;
double collision;
double *inv_sinh;
static void get_collision_matrix(
double *collision_matrix, const double *fc3_normal_squared,
const long num_band0, const long num_band, const double *frequencies,
const long (*triplets)[3], const long *triplets_map, const long num_gp,
const long *map_q, const long *rot_grid_points, const long num_ir_gp,
const long num_rot, const double *rotations_cartesian, const double *g,
const double temperature, const double unit_conversion_factor,
const double cutoff_frequency) {
long i, j, k, l, m, n, ti, r_gp, swapped;
long *gp2tp_map;
double collision;
double *inv_sinh;
gp2tp_map = create_gp2tp_map(triplets_map, num_gp);
gp2tp_map = create_gp2tp_map(triplets_map, num_gp);
#ifdef PHPYOPENMP
#pragma omp parallel for private(j, k, l, m, n, ti, r_gp, collision, inv_sinh)
#endif
for (i = 0; i < num_ir_gp; i++)
{
inv_sinh = (double *)malloc(sizeof(double) * num_band);
for (j = 0; j < num_rot; j++)
{
r_gp = rot_grid_points[i * num_rot + j];
ti = gp2tp_map[triplets_map[r_gp]];
get_inv_sinh(inv_sinh,
r_gp,
temperature,
frequencies,
triplets[ti],
triplets_map,
map_q,
num_band,
cutoff_frequency);
for (i = 0; i < num_ir_gp; i++) {
inv_sinh = (double *)malloc(sizeof(double) * num_band);
for (j = 0; j < num_rot; j++) {
r_gp = rot_grid_points[i * num_rot + j];
ti = gp2tp_map[triplets_map[r_gp]];
swapped = get_inv_sinh(inv_sinh, r_gp, temperature, frequencies,
triplets[ti], triplets_map, map_q, num_band,
cutoff_frequency);
for (k = 0; k < num_band0; k++)
{
for (l = 0; l < num_band; l++)
{
collision = 0;
for (m = 0; m < num_band; m++)
{
collision +=
fc3_normal_squared[ti * num_band0 * num_band * num_band +
k * num_band * num_band +
l * num_band + m] *
g[ti * num_band0 * num_band * num_band +
k * num_band * num_band +
l * num_band + m] *
inv_sinh[m] * unit_conversion_factor;
}
for (m = 0; m < 3; m++)
{
for (n = 0; n < 3; n++)
{
collision_matrix[k * 3 * num_ir_gp * num_band * 3 +
m * num_ir_gp * num_band * 3 +
i * num_band * 3 + l * 3 + n] +=
collision * rotations_cartesian[j * 9 + m * 3 + n];
for (k = 0; k < num_band0; k++) {
for (l = 0; l < num_band; l++) {
collision = 0;
for (m = 0; m < num_band; m++) {
if (swapped) {
collision +=
fc3_normal_squared[ti * num_band0 * num_band *
num_band +
k * num_band * num_band +
m * num_band + l] *
g[ti * num_band0 * num_band * num_band +
k * num_band * num_band + m * num_band + l] *
inv_sinh[m] * unit_conversion_factor;
} else {
collision +=
fc3_normal_squared[ti * num_band0 * num_band *
num_band +
k * num_band * num_band +
l * num_band + m] *
g[ti * num_band0 * num_band * num_band +
k * num_band * num_band + l * num_band + m] *
inv_sinh[m] * unit_conversion_factor;
}
}
for (m = 0; m < 3; m++) {
for (n = 0; n < 3; n++) {
collision_matrix[k * 3 * num_ir_gp * num_band * 3 +
m * num_ir_gp * num_band * 3 +
i * num_band * 3 + l * 3 + n] +=
collision *
rotations_cartesian[j * 9 + m * 3 + n];
}
}
}
}
}
}
}
free(inv_sinh);
inv_sinh = NULL;
}
free(inv_sinh);
inv_sinh = NULL;
}
free(gp2tp_map);
gp2tp_map = NULL;
free(gp2tp_map);
gp2tp_map = NULL;
}
static void
get_reducible_collision_matrix(double *collision_matrix,
const double *fc3_normal_squared,
const long num_band0,
const long num_band,
const double *frequencies,
const long (*triplets)[3],
const long *triplets_map,
const long num_gp,
const long *map_q,
const double *g,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency)
{
long i, j, k, l, ti;
long *gp2tp_map;
double collision;
double *inv_sinh;
static void get_reducible_collision_matrix(
double *collision_matrix, const double *fc3_normal_squared,
const long num_band0, const long num_band, const double *frequencies,
const long (*triplets)[3], const long *triplets_map, const long num_gp,
const long *map_q, const double *g, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency) {
long i, j, k, l, ti, swapped;
long *gp2tp_map;
double collision;
double *inv_sinh;
gp2tp_map = create_gp2tp_map(triplets_map, num_gp);
gp2tp_map = create_gp2tp_map(triplets_map, num_gp);
#ifdef PHPYOPENMP
#pragma omp parallel for private(j, k, l, ti, collision, inv_sinh)
#endif
for (i = 0; i < num_gp; i++)
{
inv_sinh = (double *)malloc(sizeof(double) * num_band);
ti = gp2tp_map[triplets_map[i]];
get_inv_sinh(inv_sinh,
i,
temperature,
frequencies,
triplets[ti],
triplets_map,
map_q,
num_band,
cutoff_frequency);
for (i = 0; i < num_gp; i++) {
inv_sinh = (double *)malloc(sizeof(double) * num_band);
ti = gp2tp_map[triplets_map[i]];
swapped =
get_inv_sinh(inv_sinh, i, temperature, frequencies, triplets[ti],
triplets_map, map_q, num_band, cutoff_frequency);
for (j = 0; j < num_band0; j++)
{
for (k = 0; k < num_band; k++)
{
collision = 0;
for (l = 0; l < num_band; l++)
{
collision +=
fc3_normal_squared[ti * num_band0 * num_band * num_band +
j * num_band * num_band +
k * num_band + l] *
g[ti * num_band0 * num_band * num_band +
j * num_band * num_band +
k * num_band + l] *
inv_sinh[l] * unit_conversion_factor;
for (j = 0; j < num_band0; j++) {
for (k = 0; k < num_band; k++) {
collision = 0;
for (l = 0; l < num_band; l++) {
if (swapped) {
collision +=
fc3_normal_squared[ti * num_band0 * num_band *
num_band +
j * num_band * num_band +
l * num_band + k] *
g[ti * num_band0 * num_band * num_band +
j * num_band * num_band + l * num_band + k] *
inv_sinh[l] * unit_conversion_factor;
} else {
collision +=
fc3_normal_squared[ti * num_band0 * num_band *
num_band +
j * num_band * num_band +
k * num_band + l] *
g[ti * num_band0 * num_band * num_band +
j * num_band * num_band + k * num_band + l] *
inv_sinh[l] * unit_conversion_factor;
}
}
collision_matrix[j * num_gp * num_band + i * num_band + k] +=
collision;
}
}
collision_matrix[j * num_gp * num_band + i * num_band + k] += collision;
}
free(inv_sinh);
inv_sinh = NULL;
}
free(inv_sinh);
inv_sinh = NULL;
}
free(gp2tp_map);
gp2tp_map = NULL;
free(gp2tp_map);
gp2tp_map = NULL;
}
static void get_inv_sinh(double *inv_sinh,
const long gp,
const double temperature,
const double *frequencies,
const long triplet[3],
const long *triplets_map,
const long *map_q,
const long num_band,
const double cutoff_frequency)
{
long i, gp2;
double f;
static long get_inv_sinh(double *inv_sinh, const long gp,
const double temperature, const double *frequencies,
const long triplet[3], const long *triplets_map,
const long *map_q, const long num_band,
const double cutoff_frequency) {
long i, gp2, swapped;
double f;
/* This assumes the algorithm of get_ir_triplets_at_q_perm_q1q2, */
/* where defined triplets_map[gp] == triplets_map[map_q[gp]]. */
/* If triplets_map[map_q[gp]] != map_q[gp], q1 and q2 are permuted. */
if (triplets_map[gp] == map_q[gp])
{
gp2 = triplet[2];
}
else
{
gp2 = triplet[1];
}
/* This assumes the algorithm of get_ir_triplets_at_q_perm_q1q2, */
/* where defined triplets_map[gp] == triplets_map[map_q[gp]]. */
/* If triplets_map[map_q[gp]] != map_q[gp], q1 and q2 are permuted. */
if (triplets_map[gp] == map_q[gp]) {
gp2 = triplet[2];
swapped = 0;
} else {
gp2 = triplet[1];
swapped = 1;
}
for (i = 0; i < num_band; i++)
{
f = frequencies[gp2 * num_band + i];
if (f > cutoff_frequency)
{
inv_sinh[i] = phonoc_inv_sinh_occupation(f, temperature);
for (i = 0; i < num_band; i++) {
f = frequencies[gp2 * num_band + i];
if (f > cutoff_frequency) {
inv_sinh[i] = phonoc_inv_sinh_occupation(f, temperature);
} else {
inv_sinh[i] = 0;
}
}
else
{
inv_sinh[i] = 0;
}
}
return swapped;
}
/* Symmetrically independent triplets are indexed. */
/* Inverse definition of ir_grid_points in get_BZ_triplets_at_q */
/* in triplet_grid.c. */
static long *create_gp2tp_map(const long *triplets_map,
const long num_gp)
{
long i, num_ir;
long *gp2tp_map;
static long *create_gp2tp_map(const long *triplets_map, const long num_gp) {
long i, num_ir;
long *gp2tp_map;
gp2tp_map = (long *)malloc(sizeof(long) * num_gp);
num_ir = 0;
for (i = 0; i < num_gp; i++)
{
if (triplets_map[i] == i)
{
gp2tp_map[i] = num_ir;
num_ir++;
gp2tp_map = (long *)malloc(sizeof(long) * num_gp);
num_ir = 0;
for (i = 0; i < num_gp; i++) {
if (triplets_map[i] == i) {
gp2tp_map[i] = num_ir;
num_ir++;
} else { /* This should not be used. */
gp2tp_map[i] = -1;
}
}
else
{ /* This should not be used. */
gp2tp_map[i] = -1;
}
}
return gp2tp_map;
return gp2tp_map;
}

View File

@ -37,31 +37,18 @@
#include "phonoc_array.h"
void col_get_collision_matrix(double *collision_matrix,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplets_map,
const long *map_q,
const long *rot_grid_points,
const double *rotations_cartesian,
const double *g,
const long num_ir_gp,
const long num_gp,
const long num_rot,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency);
void col_get_reducible_collision_matrix(double *collision_matrix,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplets_map,
const long *map_q,
const double *g,
const long num_gp,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency);
void col_get_collision_matrix(
double *collision_matrix, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplets_map, const long *map_q, const long *rot_grid_points,
const double *rotations_cartesian, const double *g, const long num_ir_gp,
const long num_gp, const long num_rot, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency);
void col_get_reducible_collision_matrix(
double *collision_matrix, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplets_map, const long *map_q, const double *g,
const long num_gp, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency);
#endif

1022
c/dynmat.c

File diff suppressed because it is too large Load Diff

View File

@ -36,58 +36,42 @@
#define __dynmat_H__
long dym_get_dynamical_matrix_at_q(double *dynamical_matrix,
const long num_patom,
const long num_satom,
const double *fc,
const double q[3],
const long num_patom, const long num_satom,
const double *fc, const double q[3],
const double (*svecs)[3],
const long (*multi)[2],
const double *mass,
const long *s2p_map,
const long *p2s_map,
const long (*multi)[2], const double *mass,
const long *s2p_map, const long *p2s_map,
const double (*charge_sum)[3][3],
const long with_openmp);
void dym_get_recip_dipole_dipole(double *dd, /* [natom, 3, natom, 3, (real,imag)] */
const double *dd_q0, /* [natom, 3, 3, (real,imag)] */
const double (*G_list)[3], /* [num_G, 3] */
const long num_G,
const long num_patom,
const double q_cart[3],
const double *q_direction_cart, /* must be pointer */
const double (*born)[3][3],
const double dielectric[3][3],
const double (*pos)[3], /* [num_patom, 3] */
const double factor, /* 4pi/V*unit-conv */
const double lambda,
const double tolerance);
void dym_get_recip_dipole_dipole_q0(double *dd_q0, /* [natom, 3, 3, (real,imag)] */
const double (*G_list)[3], /* [num_G, 3] */
const long num_G,
const long num_patom,
const double (*born)[3][3],
const double dielectric[3][3],
const double (*pos)[3], /* [natom, 3] */
const double lambda,
const double tolerance);
void dym_get_charge_sum(double (*charge_sum)[3][3],
const long num_patom,
const double factor,
const double q_cart[3],
void dym_get_recip_dipole_dipole(
double *dd, /* [natom, 3, natom, 3, (real,imag)] */
const double *dd_q0, /* [natom, 3, 3, (real,imag)] */
const double (*G_list)[3], /* [num_G, 3] */
const long num_G, const long num_patom, const double q_cart[3],
const double *q_direction_cart, /* must be pointer */
const double (*born)[3][3], const double dielectric[3][3],
const double (*pos)[3], /* [num_patom, 3] */
const double factor, /* 4pi/V*unit-conv */
const double lambda, const double tolerance);
void dym_get_recip_dipole_dipole_q0(
double *dd_q0, /* [natom, 3, 3, (real,imag)] */
const double (*G_list)[3], /* [num_G, 3] */
const long num_G, const long num_patom, const double (*born)[3][3],
const double dielectric[3][3], const double (*pos)[3], /* [natom, 3] */
const double lambda, const double tolerance);
void dym_get_charge_sum(double (*charge_sum)[3][3], const long num_patom,
const double factor, const double q_cart[3],
const double (*born)[3][3]);
/* fc[num_patom, num_satom, 3, 3] */
/* dm[num_comm_points, num_patom * 3, num_patom *3] */
/* comm_points[num_satom / num_patom, 3] */
/* shortest_vectors[:, 3] */
/* multiplicities[num_satom, num_patom, 2] */
void dym_transform_dynmat_to_fc(double *fc,
const double *dm,
void dym_transform_dynmat_to_fc(double *fc, const double *dm,
const double (*comm_points)[3],
const double (*svecs)[3],
const long (*multi)[2],
const double *masses,
const long *s2pp_map,
const long *fc_index_map,
const long num_patom,
const long num_satom);
const long (*multi)[2], const double *masses,
const long *s2pp_map, const long *fc_index_map,
const long num_patom, const long num_satom);
#endif

1007
c/fc3.c

File diff suppressed because it is too large Load Diff

36
c/fc3.h
View File

@ -35,35 +35,21 @@
#ifndef __fc3_H__
#define __fc3_H__
void fc3_distribute_fc3(double *fc3,
const long target,
const long source,
const long *atom_mapping,
const long num_atom,
void fc3_distribute_fc3(double *fc3, const long target, const long source,
const long *atom_mapping, const long num_atom,
const double *rot_cart);
void fc3_rotate_delta_fc2(double (*fc3)[3][3][3],
const double (*delta_fc2s)[3][3],
const double *inv_U,
const double (*delta_fc2s)[3][3], const double *inv_U,
const double (*site_sym_cart)[3][3],
const long *rot_map_syms,
const long num_atom,
const long num_site_sym,
const long num_disp);
const long *rot_map_syms, const long num_atom,
const long num_site_sym, const long num_disp);
void fc3_set_permutation_symmetry_fc3(double *fc3, const long num_atom);
void fc3_set_permutation_symmetry_compact_fc3(double *fc3,
const long p2s[],
const long s2pp[],
const long nsym_list[],
const long perms[],
const long n_satom,
const long n_patom);
void fc3_transpose_compact_fc3(double *fc3,
const long p2s[],
const long s2pp[],
const long nsym_list[],
const long perms[],
const long n_satom,
const long n_patom,
void fc3_set_permutation_symmetry_compact_fc3(
double *fc3, const long p2s[], const long s2pp[], const long nsym_list[],
const long perms[], const long n_satom, const long n_patom);
void fc3_transpose_compact_fc3(double *fc3, const long p2s[], const long s2pp[],
const long nsym_list[], const long perms[],
const long n_satom, const long n_patom,
const long t_type);
#endif

View File

@ -32,10 +32,12 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include <stdio.h>
#include <stddef.h>
#include <assert.h>
#include "grgrid.h"
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include "lagrid.h"
#include "snf3x3.h"
@ -43,62 +45,47 @@
static void reduce_grid_address(long address[3], const long D_diag[3]);
static long get_double_grid_index(const long address_double[3],
const long D_diag[3],
const long PS[3]);
const long D_diag[3], const long PS[3]);
static long get_grid_index_from_address(const long address[3],
const long D_diag[3]);
static void get_all_grid_addresses(long grid_address[][3],
const long D_diag[3]);
static void get_grid_address_from_index(long address[3],
const long grid_index,
static void get_grid_address_from_index(long address[3], const long grid_index,
const long D_diag[3]);
static void get_grid_address(long address[3],
const long address_double[3],
static void get_grid_address(long address[3], const long address_double[3],
const long PS[3]);
static void get_double_grid_address(long address_double[3],
const long address[3],
const long PS[3]);
static long rotate_grid_index(const long grid_index,
const long rotation[3][3],
const long D_diag[3],
const long PS[3]);
static void get_ir_grid_map(long *ir_grid_map,
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
const long address[3], const long PS[3]);
static long rotate_grid_index(const long grid_index, const long rotation[3][3],
const long D_diag[3], const long PS[3]);
static void get_ir_grid_map(long *ir_grid_map, const long (*rotations)[3][3],
const long num_rot, const long D_diag[3],
const long PS[3]);
long grg_get_snf3x3(long D_diag[3],
long P[3][3],
long Q[3][3],
const long A[3][3])
{
long i, j, succeeded;
long D[3][3];
long grg_get_snf3x3(long D_diag[3], long P[3][3], long Q[3][3],
const long A[3][3]) {
long i, j, succeeded;
long D[3][3];
succeeded = 0;
succeeded = 0;
if (lagmat_get_determinant_l3(A) == 0)
{
goto err;
}
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
D[i][j] = A[i][j];
if (lagmat_get_determinant_l3(A) == 0) {
goto err;
}
}
succeeded = snf3x3(D, P, Q);
for (i = 0; i < 3; i++)
{
D_diag[i] = D[i][i];
}
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
D[i][j] = A[i][j];
}
}
succeeded = snf3x3(D, P, Q);
for (i = 0; i < 3; i++) {
D_diag[i] = D[i][i];
}
err:
return succeeded;
return succeeded;
}
/*----------------------------------------*/
@ -110,40 +97,34 @@ err:
/* vectors. */
/* num_rot : Number of rotations */
long grg_transform_rotations(long (*transformed_rots)[3][3],
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
const long Q[3][3])
{
long i, j, k;
double r[3][3], Q_double[3][3];
const long (*rotations)[3][3], const long num_rot,
const long D_diag[3], const long Q[3][3]) {
long i, j, k;
double r[3][3], Q_double[3][3];
/* Compute D(Q^-1)RQ(D^-1) by three steps */
/* It is assumed that |det(Q)|=1 and Q^-1 has relatively small round-off */
/* error, and we want to divide by D carefully. */
/* 1. Compute (Q^-1)RQ */
/* 2. Compute D(Q^-1)RQ */
/* 3. Compute D(Q^-1)RQ(D^-1) */
lagmat_cast_matrix_3l_to_3d(Q_double, Q);
for (i = 0; i < num_rot; i++)
{
lagmat_get_similar_matrix_ld3(r, rotations[i], Q_double, 0);
for (j = 0; j < 3; j++)
{
for (k = 0; k < 3; k++)
{
r[j][k] *= D_diag[j];
r[j][k] /= D_diag[k];
}
/* Compute D(Q^-1)RQ(D^-1) by three steps */
/* It is assumed that |det(Q)|=1 and Q^-1 has relatively small round-off */
/* error, and we want to divide by D carefully. */
/* 1. Compute (Q^-1)RQ */
/* 2. Compute D(Q^-1)RQ */
/* 3. Compute D(Q^-1)RQ(D^-1) */
lagmat_cast_matrix_3l_to_3d(Q_double, Q);
for (i = 0; i < num_rot; i++) {
lagmat_get_similar_matrix_ld3(r, rotations[i], Q_double, 0);
for (j = 0; j < 3; j++) {
for (k = 0; k < 3; k++) {
r[j][k] *= D_diag[j];
r[j][k] /= D_diag[k];
}
}
lagmat_cast_matrix_3d_to_3l(transformed_rots[i], r);
if (!lagmat_check_identity_matrix_ld3(transformed_rots[i], r,
IDENTITY_TOL)) {
return 0;
}
}
lagmat_cast_matrix_3d_to_3l(transformed_rots[i], r);
if (!lagmat_check_identity_matrix_ld3(transformed_rots[i], r, IDENTITY_TOL))
{
return 0;
}
}
return 1;
return 1;
}
/* -------------------------------*/
@ -151,9 +132,8 @@ long grg_transform_rotations(long (*transformed_rots)[3][3],
/* -------------------------------*/
/* address : Single grid address. */
/* D_diag : Diagnal elements of D. */
void grg_get_all_grid_addresses(long (*grid_address)[3], const long D_diag[3])
{
get_all_grid_addresses(grid_address, D_diag);
void grg_get_all_grid_addresses(long (*grid_address)[3], const long D_diag[3]) {
get_all_grid_addresses(grid_address, D_diag);
}
/* -------------------------------------------------------*/
@ -164,11 +144,9 @@ void grg_get_all_grid_addresses(long (*grid_address)[3], const long D_diag[3])
/* address_double : Double grid address. */
/* address : Single grid address. */
/* PS : Shifts transformed by P. s_i is 0 or 1. */
void grg_get_double_grid_address(long address_double[3],
const long address[3],
const long PS[3])
{
get_double_grid_address(address_double, address, PS);
void grg_get_double_grid_address(long address_double[3], const long address[3],
const long PS[3]) {
get_double_grid_address(address_double, address, PS);
}
/* -------------------------------------------------------*/
@ -179,11 +157,9 @@ void grg_get_double_grid_address(long address_double[3],
/* address : Single grid address. */
/* address_double : Double grid address. */
/* PS : Shifts transformed by P. s_i is 0 or 1. */
void grg_get_grid_address(long address[3],
const long address_double[3],
const long PS[3])
{
get_grid_address(address, address_double, PS);
void grg_get_grid_address(long address[3], const long address_double[3],
const long PS[3]) {
get_grid_address(address, address_double, PS);
}
/* -------------------------------------------------*/
@ -193,10 +169,8 @@ void grg_get_grid_address(long address[3],
/* D_diag : Diagnal elements of D. */
/* PS : Shifts transformed by P. s_i is 0 or 1. */
long grg_get_double_grid_index(const long address_double[3],
const long D_diag[3],
const long PS[3])
{
return get_double_grid_index(address_double, D_diag, PS);
const long D_diag[3], const long PS[3]) {
return get_double_grid_index(address_double, D_diag, PS);
}
/* -------------------------------------------------*/
@ -204,13 +178,12 @@ long grg_get_double_grid_index(const long address_double[3],
/* -------------------------------------------------*/
/* address : Single grid address. */
/* D_diag : Diagnal elements of D. */
long grg_get_grid_index(const long address[3], const long D_diag[3])
{
long red_adrs[3];
long grg_get_grid_index(const long address[3], const long D_diag[3]) {
long red_adrs[3];
lagmat_copy_vector_l3(red_adrs, address);
reduce_grid_address(red_adrs, D_diag);
return get_grid_index_from_address(red_adrs, D_diag);
lagmat_copy_vector_l3(red_adrs, address);
reduce_grid_address(red_adrs, D_diag);
return get_grid_index_from_address(red_adrs, D_diag);
}
/* ---------------------------------------*/
@ -218,38 +191,26 @@ long grg_get_grid_index(const long address[3], const long D_diag[3])
/* ---------------------------------------*/
/* address : Single grid address. */
/* D_diag : Diagnal elements of D. */
void grg_get_grid_address_from_index(long address[3],
const long grid_index,
const long D_diag[3])
{
get_grid_address_from_index(address, grid_index, D_diag);
void grg_get_grid_address_from_index(long address[3], const long grid_index,
const long D_diag[3]) {
get_grid_address_from_index(address, grid_index, D_diag);
}
/* ---------------------------*/
/* Rotate grid point by index */
/* ---------------------------*/
long grg_rotate_grid_index(const long grid_index,
const long rotation[3][3],
const long D_diag[3],
const long PS[3])
{
return rotate_grid_index(grid_index, rotation, D_diag, PS);
long grg_rotate_grid_index(const long grid_index, const long rotation[3][3],
const long D_diag[3], const long PS[3]) {
return rotate_grid_index(grid_index, rotation, D_diag, PS);
}
/* -----------------------------*/
/* Find irreducible grid points */
/* -----------------------------*/
void grg_get_ir_grid_map(long *ir_grid_map,
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
const long PS[3])
{
get_ir_grid_map(ir_grid_map,
rotations,
num_rot,
D_diag,
PS);
void grg_get_ir_grid_map(long *ir_grid_map, const long (*rotations)[3][3],
const long num_rot, const long D_diag[3],
const long PS[3]) {
get_ir_grid_map(ir_grid_map, rotations, num_rot, D_diag, PS);
}
/* Unique reciprocal rotations are collected from input rotations. */
@ -267,92 +228,74 @@ long grg_get_reciprocal_point_group(long rec_rotations[48][3][3],
const long is_transpose)
{
long i, j, num_rot_ret, inv_exist;
const long inversion[3][3] = {
{-1, 0, 0},
{0, -1, 0},
{0, 0, -1}};
long i, j, num_rot_ret, inv_exist;
const long inversion[3][3] = {{-1, 0, 0}, {0, -1, 0}, {0, 0, -1}};
/* Collect unique rotations */
num_rot_ret = 0;
for (i = 0; i < num_rot; i++)
{
for (j = 0; j < num_rot_ret; j++)
{
if (lagmat_check_identity_matrix_l3(rotations[i], rec_rotations[j]))
{
goto escape;
}
}
if (num_rot_ret == 48)
{
goto err;
}
lagmat_copy_matrix_l3(rec_rotations[num_rot_ret], rotations[i]);
num_rot_ret++;
escape:;
}
if (is_transpose)
{
for (i = 0; i < num_rot_ret; i++)
{
lagmat_transpose_matrix_l3(rec_rotations[i], rec_rotations[i]);
}
}
if (is_time_reversal)
{
inv_exist = 0;
for (i = 0; i < num_rot_ret; i++)
{
if (lagmat_check_identity_matrix_l3(inversion, rec_rotations[i]))
{
inv_exist = 1;
break;
}
/* Collect unique rotations */
num_rot_ret = 0;
for (i = 0; i < num_rot; i++) {
for (j = 0; j < num_rot_ret; j++) {
if (lagmat_check_identity_matrix_l3(rotations[i],
rec_rotations[j])) {
goto escape;
}
}
if (num_rot_ret == 48) {
goto err;
}
lagmat_copy_matrix_l3(rec_rotations[num_rot_ret], rotations[i]);
num_rot_ret++;
escape:;
}
if (!inv_exist)
{
if (num_rot_ret > 24)
{
goto err;
}
for (i = 0; i < num_rot_ret; i++)
{
lagmat_multiply_matrix_l3(rec_rotations[num_rot_ret + i],
inversion, rec_rotations[i]);
}
num_rot_ret *= 2;
if (is_transpose) {
for (i = 0; i < num_rot_ret; i++) {
lagmat_transpose_matrix_l3(rec_rotations[i], rec_rotations[i]);
}
}
}
return num_rot_ret;
if (is_time_reversal) {
inv_exist = 0;
for (i = 0; i < num_rot_ret; i++) {
if (lagmat_check_identity_matrix_l3(inversion, rec_rotations[i])) {
inv_exist = 1;
break;
}
}
if (!inv_exist) {
if (num_rot_ret > 24) {
goto err;
}
for (i = 0; i < num_rot_ret; i++) {
lagmat_multiply_matrix_l3(rec_rotations[num_rot_ret + i],
inversion, rec_rotations[i]);
}
num_rot_ret *= 2;
}
}
return num_rot_ret;
err:
return 0;
return 0;
}
static void reduce_grid_address(long address[3], const long D_diag[3])
{
long i;
static void reduce_grid_address(long address[3], const long D_diag[3]) {
long i;
for (i = 0; i < 3; i++)
{
address[i] = lagmat_modulo_l(address[i], D_diag[i]);
}
for (i = 0; i < 3; i++) {
address[i] = lagmat_modulo_l(address[i], D_diag[i]);
}
}
static long get_double_grid_index(const long address_double[3],
const long D_diag[3],
const long PS[3])
{
long address[3];
const long D_diag[3], const long PS[3]) {
long address[3];
get_grid_address(address, address_double, PS);
reduce_grid_address(address, D_diag);
return get_grid_index_from_address(address, D_diag);
get_grid_address(address, address_double, PS);
reduce_grid_address(address, D_diag);
return get_grid_index_from_address(address, D_diag);
}
/* Here address elements have to be zero or positive. */
@ -360,133 +303,111 @@ static long get_double_grid_index(const long address_double[3],
/* done outside of this function. */
/* See kgrid.h about GRID_ORDER_XYZ information. */
static long get_grid_index_from_address(const long address[3],
const long D_diag[3])
{
const long D_diag[3]) {
#ifndef GRID_ORDER_XYZ
return (address[2] * D_diag[0] * D_diag[1] + address[1] * D_diag[0] + address[0]);
return (address[2] * D_diag[0] * D_diag[1] + address[1] * D_diag[0] +
address[0]);
#else
return (address[0] * D_diag[1] * D_diag[2] + address[1] * D_diag[2] + address[2]);
return (address[0] * D_diag[1] * D_diag[2] + address[1] * D_diag[2] +
address[2]);
#endif
}
static void get_all_grid_addresses(long grid_address[][3],
const long D_diag[3])
{
long i, j, k, grid_index;
long address[3];
const long D_diag[3]) {
long i, j, k, grid_index;
long address[3];
for (i = 0; i < D_diag[0]; i++)
{
address[0] = i;
for (j = 0; j < D_diag[1]; j++)
{
address[1] = j;
for (k = 0; k < D_diag[2]; k++)
{
address[2] = k;
grid_index = get_grid_index_from_address(address, D_diag);
lagmat_copy_vector_l3(grid_address[grid_index], address);
}
for (i = 0; i < D_diag[0]; i++) {
address[0] = i;
for (j = 0; j < D_diag[1]; j++) {
address[1] = j;
for (k = 0; k < D_diag[2]; k++) {
address[2] = k;
grid_index = get_grid_index_from_address(address, D_diag);
lagmat_copy_vector_l3(grid_address[grid_index], address);
}
}
}
}
}
/* See grg_get_grid_address_from_index */
static void get_grid_address_from_index(long address[3],
const long grid_index,
const long D_diag[3])
{
long nn;
static void get_grid_address_from_index(long address[3], const long grid_index,
const long D_diag[3]) {
long nn;
#ifndef GRID_ORDER_XYZ
nn = D_diag[0] * D_diag[1];
address[0] = grid_index % D_diag[0];
address[2] = grid_index / nn;
address[1] = (grid_index - address[2] * nn) / D_diag[0];
nn = D_diag[0] * D_diag[1];
address[0] = grid_index % D_diag[0];
address[2] = grid_index / nn;
address[1] = (grid_index - address[2] * nn) / D_diag[0];
#else
nn = D_diag[1] * D_diag[2];
address[2] = grid_index % D_diag[2];
address[0] = grid_index / nn;
address[1] = (grid_index - address[0] * nn) / D_diag[2];
nn = D_diag[1] * D_diag[2];
address[2] = grid_index % D_diag[2];
address[0] = grid_index / nn;
address[1] = (grid_index - address[0] * nn) / D_diag[2];
#endif
}
/* Usually address has to be reduced to [0, D_diag[i]) */
/* by calling reduce_grid_address after this operation. */
static void get_grid_address(long address[3],
const long address_double[3],
const long PS[3])
{
long i;
static void get_grid_address(long address[3], const long address_double[3],
const long PS[3]) {
long i;
for (i = 0; i < 3; i++)
{
address[i] = (address_double[i] - PS[i]) / 2;
}
for (i = 0; i < 3; i++) {
address[i] = (address_double[i] - PS[i]) / 2;
}
}
/* Usually address_double has to be reduced to [0, 2*D_diag[i]) */
/* by calling reduce_double_grid_address after this operation. */
static void get_double_grid_address(long address_double[3],
const long address[3],
const long PS[3])
{
long i;
const long address[3], const long PS[3]) {
long i;
for (i = 0; i < 3; i++)
{
address_double[i] = address[i] * 2 + PS[i];
}
for (i = 0; i < 3; i++) {
address_double[i] = address[i] * 2 + PS[i];
}
}
static long rotate_grid_index(const long grid_index,
const long rotation[3][3],
const long D_diag[3],
const long PS[3])
{
long adrs[3], dadrs[3], dadrs_rot[3];
static long rotate_grid_index(const long grid_index, const long rotation[3][3],
const long D_diag[3], const long PS[3]) {
long adrs[3], dadrs[3], dadrs_rot[3];
get_grid_address_from_index(adrs, grid_index, D_diag);
get_double_grid_address(dadrs, adrs, PS);
lagmat_multiply_matrix_vector_l3(dadrs_rot, rotation, dadrs);
return get_double_grid_index(dadrs_rot, D_diag, PS);
get_grid_address_from_index(adrs, grid_index, D_diag);
get_double_grid_address(dadrs, adrs, PS);
lagmat_multiply_matrix_vector_l3(dadrs_rot, rotation, dadrs);
return get_double_grid_index(dadrs_rot, D_diag, PS);
}
/* Find ir-grid points. */
/* This algorithm relies on the ir-grid index is always smallest */
/* number among symmetrically equivalent grid points. */
static void get_ir_grid_map(long *ir_grid_map,
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
const long PS[3])
{
long gp, num_gp, r_gp;
long i;
static void get_ir_grid_map(long *ir_grid_map, const long (*rotations)[3][3],
const long num_rot, const long D_diag[3],
const long PS[3]) {
long gp, num_gp, r_gp;
long i;
num_gp = D_diag[0] * D_diag[1] * D_diag[2];
num_gp = D_diag[0] * D_diag[1] * D_diag[2];
for (gp = 0; gp < num_gp; gp++)
{
ir_grid_map[gp] = num_gp;
}
/* Do not simply multithreaded this for-loop. */
/* This algorithm contains race condition in different gp's. */
for (gp = 0; gp < num_gp; gp++)
{
for (i = 0; i < num_rot; i++)
{
r_gp = rotate_grid_index(gp, rotations[i], D_diag, PS);
if (r_gp < gp)
{
ir_grid_map[gp] = ir_grid_map[r_gp];
break;
}
for (gp = 0; gp < num_gp; gp++) {
ir_grid_map[gp] = num_gp;
}
if (ir_grid_map[gp] == num_gp)
{
ir_grid_map[gp] = gp;
/* Do not simply multithreaded this for-loop. */
/* This algorithm contains race condition in different gp's. */
for (gp = 0; gp < num_gp; gp++) {
for (i = 0; i < num_rot; i++) {
r_gp = rotate_grid_index(gp, rotations[i], D_diag, PS);
if (r_gp < gp) {
ir_grid_map[gp] = ir_grid_map[r_gp];
break;
}
}
if (ir_grid_map[gp] == num_gp) {
ir_grid_map[gp] = gp;
}
}
}
}

View File

@ -37,38 +37,25 @@
#include <stddef.h>
long grg_get_snf3x3(long D_diag[3],
long P[3][3],
long Q[3][3],
long grg_get_snf3x3(long D_diag[3], long P[3][3], long Q[3][3],
const long A[3][3]);
long grg_transform_rotations(long (*transformed_rots)[3][3],
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
const long Q[3][3]);
const long (*rotations)[3][3], const long num_rot,
const long D_diag[3], const long Q[3][3]);
void grg_get_all_grid_addresses(long (*grid_address)[3], const long D_diag[3]);
void grg_get_double_grid_address(long address_double[3],
const long address[3],
void grg_get_double_grid_address(long address_double[3], const long address[3],
const long PS[3]);
void grg_get_grid_address(long address[3],
const long address_double[3],
void grg_get_grid_address(long address[3], const long address_double[3],
const long PS[3]);
long grg_get_grid_index(const long address[3],
const long D_diag[3]);
long grg_get_grid_index(const long address[3], const long D_diag[3]);
long grg_get_double_grid_index(const long address_double[3],
const long D_diag[3],
const long PS[3]);
void grg_get_grid_address_from_index(long address[3],
const long grid_index,
const long D_diag[3], const long PS[3]);
void grg_get_grid_address_from_index(long address[3], const long grid_index,
const long D_diag[3]);
long grg_rotate_grid_index(const long grid_index,
const long rotations[3][3],
const long D_diag[3],
const long PS[3]);
void grg_get_ir_grid_map(long *ir_grid_map,
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
long grg_rotate_grid_index(const long grid_index, const long rotations[3][3],
const long D_diag[3], const long PS[3]);
void grg_get_ir_grid_map(long *ir_grid_map, const long (*rotations)[3][3],
const long num_rot, const long D_diag[3],
const long PS[3]);
long grg_get_reciprocal_point_group(long rec_rotations[48][3][3],
const long (*rotations)[3][3],

View File

@ -34,76 +34,58 @@
#include "gridsys.h"
#include <stdio.h>
#include <stdlib.h>
#include "bzgrid.h"
#include "lagrid.h"
#include "grgrid.h"
#include "lagrid.h"
#include "tetrahedron_method.h"
#include "triplet.h"
#include "triplet_iw.h"
#include <stdio.h>
#include <stdlib.h>
void gridsys_get_all_grid_addresses(long (*gr_grid_addresses)[3],
const long D_diag[3])
{
grg_get_all_grid_addresses(gr_grid_addresses, D_diag);
const long D_diag[3]) {
grg_get_all_grid_addresses(gr_grid_addresses, D_diag);
}
void gridsys_get_double_grid_address(long address_double[3],
const long address[3],
const long PS[3])
{
grg_get_double_grid_address(address_double, address, PS);
const long address[3], const long PS[3]) {
grg_get_double_grid_address(address_double, address, PS);
}
void gridsys_get_grid_address_from_index(long address[3],
const long grid_index,
const long D_diag[3])
{
grg_get_grid_address_from_index(address, grid_index, D_diag);
void gridsys_get_grid_address_from_index(long address[3], const long grid_index,
const long D_diag[3]) {
grg_get_grid_address_from_index(address, grid_index, D_diag);
}
long gridsys_get_double_grid_index(const long address_double[3],
const long D_diag[3],
const long PS[3])
{
return grg_get_double_grid_index(address_double, D_diag, PS);
const long D_diag[3], const long PS[3]) {
return grg_get_double_grid_index(address_double, D_diag, PS);
}
/* From single address to grid index */
long gridsys_get_grid_index_from_address(const long address[3],
const long D_diag[3])
{
return grg_get_grid_index(address, D_diag);
const long D_diag[3]) {
return grg_get_grid_index(address, D_diag);
}
long gridsys_rotate_grid_index(const long grid_index,
const long rotation[3][3],
const long D_diag[3],
const long PS[3])
{
return grg_rotate_grid_index(grid_index, rotation, D_diag, PS);
long gridsys_rotate_grid_index(const long grid_index, const long rotation[3][3],
const long D_diag[3], const long PS[3]) {
return grg_rotate_grid_index(grid_index, rotation, D_diag, PS);
}
long gridsys_get_reciprocal_point_group(long rec_rotations[48][3][3],
const long (*rotations)[3][3],
const long num_rot,
const long is_time_reversal)
{
return grg_get_reciprocal_point_group(rec_rotations,
rotations,
num_rot,
is_time_reversal,
1);
const long is_time_reversal) {
return grg_get_reciprocal_point_group(rec_rotations, rotations, num_rot,
is_time_reversal, 1);
}
long gridsys_get_snf3x3(long D_diag[3],
long P[3][3],
long Q[3][3],
const long A[3][3])
{
return grg_get_snf3x3(D_diag, P, Q, A);
long gridsys_get_snf3x3(long D_diag[3], long P[3][3], long Q[3][3],
const long A[3][3]) {
return grg_get_snf3x3(D_diag, P, Q, A);
}
/* Rotation matrices with respect to reciprocal basis vectors are
@ -111,43 +93,33 @@ long gridsys_get_snf3x3(long D_diag[3],
* used always in GRGrid handling. */
long gridsys_transform_rotations(long (*transformed_rots)[3][3],
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
const long Q[3][3])
{
long succeeded;
succeeded = grg_transform_rotations(transformed_rots,
rotations,
num_rot,
D_diag,
Q);
return succeeded;
const long num_rot, const long D_diag[3],
const long Q[3][3]) {
long succeeded;
succeeded = grg_transform_rotations(transformed_rots, rotations, num_rot,
D_diag, Q);
return succeeded;
}
double gridsys_get_thm_integration_weight(const double omega,
const double tetrahedra_omegas[24][4],
const char function)
{
return thm_get_integration_weight(omega, tetrahedra_omegas, function);
const char function) {
return thm_get_integration_weight(omega, tetrahedra_omegas, function);
}
/* Get one dataset of relative grid address used for tetrahedron */
/* method. rec_lattice is used to choose the one. */
/* rec_lattice : microzone basis vectors in column vectors */
void gridsys_get_thm_relative_grid_address(long relative_grid_addresses[24][4][3],
const double rec_lattice[3][3])
{
thm_get_relative_grid_address(relative_grid_addresses, rec_lattice);
void gridsys_get_thm_relative_grid_address(
long relative_grid_addresses[24][4][3], const double rec_lattice[3][3]) {
thm_get_relative_grid_address(relative_grid_addresses, rec_lattice);
}
/* The rotations are those after proper transformation in GRGrid. */
void gridsys_get_ir_grid_map(long *ir_grid_map,
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
const long PS[3])
{
grg_get_ir_grid_map(ir_grid_map, rotations, num_rot, D_diag, PS);
void gridsys_get_ir_grid_map(long *ir_grid_map, const long (*rotations)[3][3],
const long num_rot, const long D_diag[3],
const long PS[3]) {
grg_get_ir_grid_map(ir_grid_map, rotations, num_rot, D_diag, PS);
}
/* Find shortest grid points from Gamma considering periodicity of */
@ -173,197 +145,130 @@ void gridsys_get_ir_grid_map(long *ir_grid_map,
/* len(bzg2grg) == len(bz_grid_addresses) <= product(D_diag + 1). */
/* (function return) size : */
/* Number of bz_grid_addresses stored. */
long gridsys_get_bz_grid_addresses(long (*bz_grid_addresses)[3],
long *bz_map,
long *bzg2grg,
const long D_diag[3],
const long Q[3][3],
const long PS[3],
long gridsys_get_bz_grid_addresses(long (*bz_grid_addresses)[3], long *bz_map,
long *bzg2grg, const long D_diag[3],
const long Q[3][3], const long PS[3],
const double rec_lattice[3][3],
const long type)
{
BZGrid *bzgrid;
long i, j, size;
const long type) {
BZGrid *bzgrid;
long i, j, size;
if ((bzgrid = (BZGrid *)malloc(sizeof(BZGrid))) == NULL)
{
warning_print("Memory could not be allocated.");
return 0;
}
bzgrid->addresses = bz_grid_addresses;
bzgrid->gp_map = bz_map;
bzgrid->bzg2grg = bzg2grg;
bzgrid->type = type;
for (i = 0; i < 3; i++)
{
bzgrid->D_diag[i] = D_diag[i];
bzgrid->PS[i] = PS[i];
for (j = 0; j < 3; j++)
{
bzgrid->Q[i][j] = Q[i][j];
bzgrid->reclat[i][j] = rec_lattice[i][j];
if ((bzgrid = (BZGrid *)malloc(sizeof(BZGrid))) == NULL) {
warning_print("Memory could not be allocated.");
return 0;
}
}
if (bzg_get_bz_grid_addresses(bzgrid))
{
size = bzgrid->size;
}
else
{
size = 0;
}
bzgrid->addresses = bz_grid_addresses;
bzgrid->gp_map = bz_map;
bzgrid->bzg2grg = bzg2grg;
bzgrid->type = type;
for (i = 0; i < 3; i++) {
bzgrid->D_diag[i] = D_diag[i];
bzgrid->PS[i] = PS[i];
for (j = 0; j < 3; j++) {
bzgrid->Q[i][j] = Q[i][j];
bzgrid->reclat[i][j] = rec_lattice[i][j];
}
}
free(bzgrid);
bzgrid = NULL;
if (bzg_get_bz_grid_addresses(bzgrid)) {
size = bzgrid->size;
} else {
size = 0;
}
return size;
free(bzgrid);
bzgrid = NULL;
return size;
}
long gridsys_get_triplets_at_q(long *map_triplets,
long *map_q,
const long grid_point,
const long D_diag[3],
const long is_time_reversal,
const long num_rot,
long gridsys_get_triplets_at_q(long *map_triplets, long *map_q,
const long grid_point, const long D_diag[3],
const long is_time_reversal, const long num_rot,
const long (*rec_rotations)[3][3],
const long swappable)
{
return tpl_get_triplets_reciprocal_mesh_at_q(map_triplets,
map_q,
grid_point,
D_diag,
is_time_reversal,
num_rot,
rec_rotations,
swappable);
const long swappable) {
return tpl_get_triplets_reciprocal_mesh_at_q(
map_triplets, map_q, grid_point, D_diag, is_time_reversal, num_rot,
rec_rotations, swappable);
}
long gridsys_get_BZ_triplets_at_q(long (*triplets)[3],
const long grid_point,
long gridsys_get_BZ_triplets_at_q(long (*triplets)[3], const long grid_point,
const long (*bz_grid_addresses)[3],
const long *bz_map,
const long *map_triplets,
const long *bz_map, const long *map_triplets,
const long num_map_triplets,
const long D_diag[3],
const long Q[3][3],
const long bz_grid_type)
{
ConstBZGrid *bzgrid;
long i, j, num_ir;
const long D_diag[3], const long Q[3][3],
const long bz_grid_type) {
ConstBZGrid *bzgrid;
long i, j, num_ir;
if ((bzgrid = (ConstBZGrid *)malloc(sizeof(ConstBZGrid))) == NULL)
{
warning_print("Memory could not be allocated.");
return 0;
}
bzgrid->addresses = bz_grid_addresses;
bzgrid->gp_map = bz_map;
bzgrid->type = bz_grid_type;
for (i = 0; i < 3; i++)
{
bzgrid->D_diag[i] = D_diag[i];
bzgrid->PS[i] = 0;
for (j = 0; j < 3; j++)
{
bzgrid->Q[i][j] = Q[i][j];
if ((bzgrid = (ConstBZGrid *)malloc(sizeof(ConstBZGrid))) == NULL) {
warning_print("Memory could not be allocated.");
return 0;
}
}
bzgrid->size = num_map_triplets;
num_ir = tpl_get_BZ_triplets_at_q(triplets,
grid_point,
bzgrid,
map_triplets);
free(bzgrid);
bzgrid = NULL;
bzgrid->addresses = bz_grid_addresses;
bzgrid->gp_map = bz_map;
bzgrid->type = bz_grid_type;
for (i = 0; i < 3; i++) {
bzgrid->D_diag[i] = D_diag[i];
bzgrid->PS[i] = 0;
for (j = 0; j < 3; j++) {
bzgrid->Q[i][j] = Q[i][j];
}
}
bzgrid->size = num_map_triplets;
return num_ir;
num_ir =
tpl_get_BZ_triplets_at_q(triplets, grid_point, bzgrid, map_triplets);
free(bzgrid);
bzgrid = NULL;
return num_ir;
}
/* relative_grid_addresses are given as P multipled with those from */
/* dataset, i.e., */
/* np.dot(relative_grid_addresses, P.T) */
long gridsys_get_integration_weight(double *iw,
char *iw_zero,
const double *frequency_points,
const long num_band0,
const long relative_grid_address[24][4][3],
const long D_diag[3],
const long (*triplets)[3],
const long num_triplets,
const long (*bz_grid_addresses)[3],
const long *bz_map,
const long bz_grid_type,
const double *frequencies1,
const long num_band1,
const double *frequencies2,
const long num_band2,
const long tp_type,
const long openmp_per_triplets,
const long openmp_per_bands)
{
ConstBZGrid *bzgrid;
long i;
long gridsys_get_integration_weight(
double *iw, char *iw_zero, const double *frequency_points,
const long num_band0, const long relative_grid_address[24][4][3],
const long D_diag[3], const long (*triplets)[3], const long num_triplets,
const long (*bz_grid_addresses)[3], const long *bz_map,
const long bz_grid_type, const double *frequencies1, const long num_band1,
const double *frequencies2, const long num_band2, const long tp_type,
const long openmp_per_triplets, const long openmp_per_bands) {
ConstBZGrid *bzgrid;
long i;
if ((bzgrid = (ConstBZGrid *)malloc(sizeof(ConstBZGrid))) == NULL)
{
warning_print("Memory could not be allocated.");
return 0;
}
if ((bzgrid = (ConstBZGrid *)malloc(sizeof(ConstBZGrid))) == NULL) {
warning_print("Memory could not be allocated.");
return 0;
}
bzgrid->addresses = bz_grid_addresses;
bzgrid->gp_map = bz_map;
bzgrid->type = bz_grid_type;
for (i = 0; i < 3; i++)
{
bzgrid->D_diag[i] = D_diag[i];
}
bzgrid->addresses = bz_grid_addresses;
bzgrid->gp_map = bz_map;
bzgrid->type = bz_grid_type;
for (i = 0; i < 3; i++) {
bzgrid->D_diag[i] = D_diag[i];
}
tpl_get_integration_weight(iw,
iw_zero,
frequency_points,
num_band0,
relative_grid_address,
triplets,
num_triplets,
bzgrid,
frequencies1,
num_band1,
frequencies2,
num_band2,
tp_type,
openmp_per_triplets,
openmp_per_bands);
free(bzgrid);
bzgrid = NULL;
tpl_get_integration_weight(
iw, iw_zero, frequency_points, num_band0, relative_grid_address,
triplets, num_triplets, bzgrid, frequencies1, num_band1, frequencies2,
num_band2, tp_type, openmp_per_triplets, openmp_per_bands);
free(bzgrid);
bzgrid = NULL;
return 1;
return 1;
}
void gridsys_get_integration_weight_with_sigma(double *iw,
char *iw_zero,
const double sigma,
const double sigma_cutoff,
const double *frequency_points,
const long num_band0,
const long (*triplets)[3],
const long num_triplets,
const double *frequencies,
const long num_band,
const long tp_type)
{
tpl_get_integration_weight_with_sigma(iw,
iw_zero,
sigma,
sigma_cutoff,
frequency_points,
num_band0,
triplets,
num_triplets,
frequencies,
num_band,
tp_type);
void gridsys_get_integration_weight_with_sigma(
double *iw, char *iw_zero, const double sigma, const double sigma_cutoff,
const double *frequency_points, const long num_band0,
const long (*triplets)[3], const long num_triplets,
const double *frequencies, const long num_band, const long tp_type) {
tpl_get_integration_weight_with_sigma(
iw, iw_zero, sigma, sigma_cutoff, frequency_points, num_band0, triplets,
num_triplets, frequencies, num_band, tp_type);
}

View File

@ -36,104 +36,68 @@
#define __gridsys_H__
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
void gridsys_get_all_grid_addresses(long (*gr_grid_addresses)[3],
const long D_diag[3]);
void gridsys_get_double_grid_address(long address_double[3],
const long address[3],
const long PS[3]);
void gridsys_get_grid_address_from_index(long address[3],
const long grid_index,
const long D_diag[3]);
long gridsys_get_double_grid_index(const long address_double[3],
const long D_diag[3],
const long PS[3]);
long gridsys_get_grid_index_from_address(const long address[3],
const long D_diag[3]);
long gridsys_rotate_grid_index(const long grid_index,
const long rotation[3][3],
const long D_diag[3],
const long PS[3]);
long gridsys_get_reciprocal_point_group(long rec_rotations[48][3][3],
const long (*rotations)[3][3],
const long num_rot,
const long is_time_reversal);
long gridsys_get_snf3x3(long D_diag[3],
long P[3][3],
long Q[3][3],
const long A[3][3]);
long gridsys_transform_rotations(long (*transformed_rots)[3][3],
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
const long Q[3][3]);
double gridsys_get_thm_integration_weight(const double omega,
const double tetrahedra_omegas[24][4],
const char function);
void gridsys_get_thm_relative_grid_address(long relative_grid_addresses[24][4][3],
const double rec_lattice[3][3]);
void gridsys_get_ir_grid_map(long *ir_grid_map,
void gridsys_get_all_grid_addresses(long (*gr_grid_addresses)[3],
const long D_diag[3]);
void gridsys_get_double_grid_address(long address_double[3],
const long address[3], const long PS[3]);
void gridsys_get_grid_address_from_index(long address[3], const long grid_index,
const long D_diag[3]);
long gridsys_get_double_grid_index(const long address_double[3],
const long D_diag[3], const long PS[3]);
long gridsys_get_grid_index_from_address(const long address[3],
const long D_diag[3]);
long gridsys_rotate_grid_index(const long grid_index, const long rotation[3][3],
const long D_diag[3], const long PS[3]);
long gridsys_get_reciprocal_point_group(long rec_rotations[48][3][3],
const long (*rotations)[3][3],
const long num_rot,
const long is_time_reversal);
long gridsys_get_snf3x3(long D_diag[3], long P[3][3], long Q[3][3],
const long A[3][3]);
long gridsys_transform_rotations(long (*transformed_rots)[3][3],
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
const long PS[3]);
long gridsys_get_bz_grid_addresses(long (*bz_grid_addresses)[3],
long *bz_map,
long *bzg2grg,
const long D_diag[3],
const long Q[3][3],
const long PS[3],
const double rec_lattice[3][3],
const long type);
long gridsys_get_triplets_at_q(long *map_triplets,
long *map_q,
const long grid_point,
const long D_diag[3],
const long is_time_reversal,
const long num_rot,
const long (*rec_rotations)[3][3],
const long swappable);
long gridsys_get_BZ_triplets_at_q(long (*triplets)[3],
const long grid_point,
const long (*bz_grid_addresses)[3],
const long *bz_map,
const long *map_triplets,
const long num_map_triplets,
const long D_diag[3],
const long Q[3][3],
const long bz_grid_type);
long gridsys_get_integration_weight(double *iw,
char *iw_zero,
const double *frequency_points,
const long num_band0,
const long relative_grid_address[24][4][3],
const long D_diag[3],
const long (*triplets)[3],
const long num_triplets,
const long (*bz_grid_addresses)[3],
const long *bz_map,
const long bz_grid_type,
const double *frequencies1,
const long num_band1,
const double *frequencies2,
const long num_band2,
const long tp_type,
const long openmp_per_triplets,
const long openmp_per_bands);
void gridsys_get_integration_weight_with_sigma(double *iw,
char *iw_zero,
const double sigma,
const double sigma_cutoff,
const double *frequency_points,
const long num_band0,
const long (*triplets)[3],
const long num_triplets,
const double *frequencies,
const long num_band,
const long tp_type);
const long num_rot, const long D_diag[3],
const long Q[3][3]);
double gridsys_get_thm_integration_weight(const double omega,
const double tetrahedra_omegas[24][4],
const char function);
void gridsys_get_thm_relative_grid_address(
long relative_grid_addresses[24][4][3], const double rec_lattice[3][3]);
void gridsys_get_ir_grid_map(long *ir_grid_map, const long (*rotations)[3][3],
const long num_rot, const long D_diag[3],
const long PS[3]);
long gridsys_get_bz_grid_addresses(long (*bz_grid_addresses)[3], long *bz_map,
long *bzg2grg, const long D_diag[3],
const long Q[3][3], const long PS[3],
const double rec_lattice[3][3],
const long type);
long gridsys_get_triplets_at_q(long *map_triplets, long *map_q,
const long grid_point, const long D_diag[3],
const long is_time_reversal, const long num_rot,
const long (*rec_rotations)[3][3],
const long swappable);
long gridsys_get_BZ_triplets_at_q(long (*triplets)[3], const long grid_point,
const long (*bz_grid_addresses)[3],
const long *bz_map, const long *map_triplets,
const long num_map_triplets,
const long D_diag[3], const long Q[3][3],
const long bz_grid_type);
long gridsys_get_integration_weight(
double *iw, char *iw_zero, const double *frequency_points,
const long num_band0, const long relative_grid_address[24][4][3],
const long D_diag[3], const long (*triplets)[3], const long num_triplets,
const long (*bz_grid_addresses)[3], const long *bz_map,
const long bz_grid_type, const double *frequencies1, const long num_band1,
const double *frequencies2, const long num_band2, const long tp_type,
const long openmp_per_triplets, const long openmp_per_bands);
void gridsys_get_integration_weight_with_sigma(
double *iw, char *iw_zero, const double sigma, const double sigma_cutoff,
const double *frequency_points, const long num_band0,
const long (*triplets)[3], const long num_triplets,
const double *frequencies, const long num_band, const long tp_type);
#ifdef __cplusplus
}

View File

@ -32,568 +32,411 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include "imag_self_energy_with_g.h"
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include "lagrid.h"
#include "phonoc_array.h"
#include "phonoc_utils.h"
#include "imag_self_energy_with_g.h"
#include "triplet.h"
static long ise_set_g_pos_frequency_point(long (*g_pos)[4],
const long num_band0,
const long num_band,
const char *g_zero);
static void
detailed_imag_self_energy_at_triplet(double *detailed_imag_self_energy,
double *imag_self_energy,
const long num_band0,
const long num_band,
const double *fc3_normal_squared,
const double *frequencies,
const long triplet[3],
const double *g1,
const double *g2_3,
const char *g_zero,
const double *temperatures,
const long num_temps,
const double cutoff_frequency);
static double
collect_detailed_imag_self_energy(double *imag_self_energy,
const long num_band,
const double *fc3_normal_squared,
const double *n1,
const double *n2,
const double *g1,
const double *g2_3,
const char *g_zero);
static double
collect_detailed_imag_self_energy_0K(double *imag_self_energy,
const long num_band,
const double *fc3_normal_squared,
const double *n1,
const double *n2,
const double *g,
const char *g_zero);
static void set_occupations(double *n1,
double *n2,
const long num_band,
const double temperature,
const long triplet[3],
static void detailed_imag_self_energy_at_triplet(
double *detailed_imag_self_energy, double *imag_self_energy,
const long num_band0, const long num_band, const double *fc3_normal_squared,
const double *frequencies, const long triplet[3], const double *g1,
const double *g2_3, const char *g_zero, const double *temperatures,
const long num_temps, const double cutoff_frequency);
static double collect_detailed_imag_self_energy(
double *imag_self_energy, const long num_band,
const double *fc3_normal_squared, const double *n1, const double *n2,
const double *g1, const double *g2_3, const char *g_zero);
static double collect_detailed_imag_self_energy_0K(
double *imag_self_energy, const long num_band,
const double *fc3_normal_squared, const double *n1, const double *n2,
const double *g, const char *g_zero);
static void set_occupations(double *n1, double *n2, const long num_band,
const double temperature, const long triplet[3],
const double *frequencies,
const double cutoff_frequency);
void ise_get_imag_self_energy_at_bands_with_g(double *imag_self_energy,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const double *g,
const char *g_zero,
const double temperature,
const double cutoff_frequency,
const long num_frequency_points,
const long frequency_point_index)
{
long i, j, num_triplets, num_band0, num_band, num_band_prod;
long num_g_pos, g_index_dims, g_index_shift;
long(*g_pos)[4];
double *ise;
long at_a_frequency_point;
void ise_get_imag_self_energy_at_bands_with_g(
double *imag_self_energy, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplet_weights, const double *g, const char *g_zero,
const double temperature, const double cutoff_frequency,
const long num_frequency_points, const long frequency_point_index) {
long i, j, num_triplets, num_band0, num_band, num_band_prod;
long num_g_pos, g_index_dims, g_index_shift;
long(*g_pos)[4];
double *ise;
long at_a_frequency_point;
g_pos = NULL;
ise = NULL;
g_pos = NULL;
ise = NULL;
num_triplets = fc3_normal_squared->dims[0];
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
num_band_prod = num_band0 * num_band * num_band;
ise = (double *)malloc(sizeof(double) * num_triplets * num_band0);
num_triplets = fc3_normal_squared->dims[0];
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
num_band_prod = num_band0 * num_band * num_band;
ise = (double *)malloc(sizeof(double) * num_triplets * num_band0);
if (frequency_point_index < 0)
{
/* frequency_points == frequencies at bands */
at_a_frequency_point = 0;
g_index_dims = num_band_prod;
g_index_shift = 0;
}
else
{
/* At an arbitrary frequency point. */
at_a_frequency_point = 1;
g_index_dims = num_frequency_points * num_band * num_band;
g_index_shift = frequency_point_index * num_band * num_band;
}
if (frequency_point_index < 0) {
/* frequency_points == frequencies at bands */
at_a_frequency_point = 0;
g_index_dims = num_band_prod;
g_index_shift = 0;
} else {
/* At an arbitrary frequency point. */
at_a_frequency_point = 1;
g_index_dims = num_frequency_points * num_band * num_band;
g_index_shift = frequency_point_index * num_band * num_band;
}
#ifdef PHPYOPENMP
#pragma omp parallel for private(num_g_pos, j, g_pos)
#endif
for (i = 0; i < num_triplets; i++)
{
g_pos = (long(*)[4])malloc(sizeof(long[4]) * num_band_prod);
/* ise_set_g_pos only works for the case of frquency points at */
/* bands. For frequency sampling mode, g_zero is assumed all */
/* with the array shape of (num_triplets, num_band0, num_band, */
/* num_band). */
if (at_a_frequency_point)
{
num_g_pos = ise_set_g_pos_frequency_point(
g_pos,
num_band0,
num_band,
g_zero + i * g_index_dims + g_index_shift);
}
else
{
num_g_pos = ise_set_g_pos(g_pos,
num_band0,
num_band,
g_zero + i * num_band_prod);
for (i = 0; i < num_triplets; i++) {
g_pos = (long(*)[4])malloc(sizeof(long[4]) * num_band_prod);
/* ise_set_g_pos only works for the case of frquency points at */
/* bands. For frequency sampling mode, g_zero is assumed all */
/* with the array shape of (num_triplets, num_band0, num_band, */
/* num_band). */
if (at_a_frequency_point) {
num_g_pos = ise_set_g_pos_frequency_point(
g_pos, num_band0, num_band,
g_zero + i * g_index_dims + g_index_shift);
} else {
num_g_pos = ise_set_g_pos(g_pos, num_band0, num_band,
g_zero + i * num_band_prod);
}
ise_imag_self_energy_at_triplet(
ise + i * num_band0, num_band0, num_band,
fc3_normal_squared->data + i * num_band_prod, frequencies,
triplets[i], triplet_weights[i],
g + i * g_index_dims + g_index_shift,
g + (i + num_triplets) * g_index_dims + g_index_shift, g_pos,
num_g_pos, &temperature, 1, cutoff_frequency, 0,
at_a_frequency_point);
free(g_pos);
g_pos = NULL;
}
ise_imag_self_energy_at_triplet(
ise + i * num_band0,
num_band0,
num_band,
fc3_normal_squared->data + i * num_band_prod,
frequencies,
triplets[i],
triplet_weights[i],
g + i * g_index_dims + g_index_shift,
g + (i + num_triplets) * g_index_dims + g_index_shift,
g_pos,
num_g_pos,
&temperature,
1,
cutoff_frequency,
0,
at_a_frequency_point);
free(g_pos);
g_pos = NULL;
}
for (i = 0; i < num_band0; i++)
{
imag_self_energy[i] = 0;
}
for (i = 0; i < num_triplets; i++)
{
for (j = 0; j < num_band0; j++)
{
imag_self_energy[j] += ise[i * num_band0 + j];
for (i = 0; i < num_band0; i++) {
imag_self_energy[i] = 0;
}
}
free(ise);
ise = NULL;
for (i = 0; i < num_triplets; i++) {
for (j = 0; j < num_band0; j++) {
imag_self_energy[j] += ise[i * num_band0 + j];
}
}
free(ise);
ise = NULL;
}
void ise_get_detailed_imag_self_energy_at_bands_with_g(double *detailed_imag_self_energy,
double *imag_self_energy_N,
double *imag_self_energy_U,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const long (*bz_grid_addresses)[3],
const double *g,
const char *g_zero,
const double temperature,
const double cutoff_frequency)
{
double *ise;
long i, j, num_triplets, num_band0, num_band, num_band_prod;
long *is_N;
double ise_tmp, N, U;
void ise_get_detailed_imag_self_energy_at_bands_with_g(
double *detailed_imag_self_energy, double *imag_self_energy_N,
double *imag_self_energy_U, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplet_weights, const long (*bz_grid_addresses)[3],
const double *g, const char *g_zero, const double temperature,
const double cutoff_frequency) {
double *ise;
long i, j, num_triplets, num_band0, num_band, num_band_prod;
long *is_N;
double ise_tmp, N, U;
ise = NULL;
is_N = NULL;
ise = NULL;
is_N = NULL;
num_triplets = fc3_normal_squared->dims[0];
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
num_band_prod = num_band0 * num_band * num_band;
ise = (double *)malloc(sizeof(double) * num_triplets * num_band0);
num_triplets = fc3_normal_squared->dims[0];
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
num_band_prod = num_band0 * num_band * num_band;
ise = (double *)malloc(sizeof(double) * num_triplets * num_band0);
/* detailed_imag_self_energy has the same shape as fc3_normal_squared. */
/* detailed_imag_self_energy has the same shape as fc3_normal_squared. */
#ifdef PHPYOPENMP
#pragma omp parallel for
#endif
for (i = 0; i < num_triplets; i++)
{
detailed_imag_self_energy_at_triplet(detailed_imag_self_energy + i * num_band_prod,
ise + i * num_band0,
num_band0,
num_band,
fc3_normal_squared->data + i * num_band_prod,
frequencies,
triplets[i],
g + i * num_band_prod,
g + (i + num_triplets) * num_band_prod,
g_zero + i * num_band_prod,
&temperature,
1,
cutoff_frequency);
}
is_N = (long *)malloc(sizeof(long) * num_triplets);
for (i = 0; i < num_triplets; i++)
{
is_N[i] = tpl_is_N(triplets[i], bz_grid_addresses);
}
for (i = 0; i < num_band0; i++)
{
N = 0;
U = 0;
/* #ifdef PHPYOPENMP */
/* #pragma omp parallel for private(ise_tmp) reduction(+:N,U) */
/* #endif */
for (j = 0; j < num_triplets; j++)
{
ise_tmp = ise[j * num_band0 + i] * triplet_weights[j];
if (is_N[j])
{
N += ise_tmp;
}
else
{
U += ise_tmp;
}
for (i = 0; i < num_triplets; i++) {
detailed_imag_self_energy_at_triplet(
detailed_imag_self_energy + i * num_band_prod, ise + i * num_band0,
num_band0, num_band, fc3_normal_squared->data + i * num_band_prod,
frequencies, triplets[i], g + i * num_band_prod,
g + (i + num_triplets) * num_band_prod, g_zero + i * num_band_prod,
&temperature, 1, cutoff_frequency);
}
imag_self_energy_N[i] = N;
imag_self_energy_U[i] = U;
}
free(is_N);
is_N = NULL;
free(ise);
ise = NULL;
is_N = (long *)malloc(sizeof(long) * num_triplets);
for (i = 0; i < num_triplets; i++) {
is_N[i] = tpl_is_N(triplets[i], bz_grid_addresses);
}
for (i = 0; i < num_band0; i++) {
N = 0;
U = 0;
/* #ifdef PHPYOPENMP */
/* #pragma omp parallel for private(ise_tmp) reduction(+:N,U) */
/* #endif */
for (j = 0; j < num_triplets; j++) {
ise_tmp = ise[j * num_band0 + i] * triplet_weights[j];
if (is_N[j]) {
N += ise_tmp;
} else {
U += ise_tmp;
}
}
imag_self_energy_N[i] = N;
imag_self_energy_U[i] = U;
}
free(is_N);
is_N = NULL;
free(ise);
ise = NULL;
}
void ise_imag_self_energy_at_triplet(double *imag_self_energy,
const long num_band0,
const long num_band,
const double *fc3_normal_squared,
const double *frequencies,
const long triplet[3],
const long triplet_weight,
const double *g1,
const double *g2_3,
const long (*g_pos)[4],
const long num_g_pos,
const double *temperatures,
const long num_temps,
const double cutoff_frequency,
const long openmp_at_bands,
const long at_a_frequency_point)
{
long i, j;
double *n1, *n2;
long g_pos_3;
void ise_imag_self_energy_at_triplet(
double *imag_self_energy, const long num_band0, const long num_band,
const double *fc3_normal_squared, const double *frequencies,
const long triplet[3], const long triplet_weight, const double *g1,
const double *g2_3, const long (*g_pos)[4], const long num_g_pos,
const double *temperatures, const long num_temps,
const double cutoff_frequency, const long openmp_at_bands,
const long at_a_frequency_point) {
long i, j;
double *n1, *n2;
long g_pos_3;
n1 = (double *)malloc(sizeof(double) * num_temps * num_band);
n2 = (double *)malloc(sizeof(double) * num_temps * num_band);
for (i = 0; i < num_temps; i++)
{
set_occupations(n1 + i * num_band,
n2 + i * num_band,
num_band,
temperatures[i],
triplet,
frequencies,
cutoff_frequency);
}
for (i = 0; i < num_band0 * num_temps; i++)
{
imag_self_energy[i] = 0;
}
/* Do not use OpenMP here!! */
/* g_pos[i][0] takes value 0 <= x < num_band0 only, */
/* which causes race condition. */
for (i = 0; i < num_g_pos; i++)
{
if (at_a_frequency_point)
{
/* At an arbitrary frequency point */
g_pos_3 = g_pos[i][3] % (num_band * num_band);
n1 = (double *)malloc(sizeof(double) * num_temps * num_band);
n2 = (double *)malloc(sizeof(double) * num_temps * num_band);
for (i = 0; i < num_temps; i++) {
set_occupations(n1 + i * num_band, n2 + i * num_band, num_band,
temperatures[i], triplet, frequencies,
cutoff_frequency);
}
else
{
/* frequency_points == frequencies at bands */
g_pos_3 = g_pos[i][3];
for (i = 0; i < num_band0 * num_temps; i++) {
imag_self_energy[i] = 0;
}
for (j = 0; j < num_temps; j++)
{
if (n1[j * num_band + g_pos[i][1]] < 0 ||
n2[j * num_band + g_pos[i][2]] < 0)
{
;
}
else
{
if (temperatures[j] > 0)
{
imag_self_energy[j * num_band0 + g_pos[i][0]] +=
((n1[j * num_band + g_pos[i][1]] +
n2[j * num_band + g_pos[i][2]] + 1) *
g1[g_pos_3] +
(n1[j * num_band + g_pos[i][1]] -
n2[j * num_band + g_pos[i][2]]) *
g2_3[g_pos_3]) *
fc3_normal_squared[g_pos[i][3]] * triplet_weight;
/* Do not use OpenMP here!! */
/* g_pos[i][0] takes value 0 <= x < num_band0 only, */
/* which causes race condition. */
for (i = 0; i < num_g_pos; i++) {
if (at_a_frequency_point) {
/* At an arbitrary frequency point */
g_pos_3 = g_pos[i][3] % (num_band * num_band);
} else {
/* frequency_points == frequencies at bands */
g_pos_3 = g_pos[i][3];
}
else
{
imag_self_energy[j * num_band0 + g_pos[i][0]] +=
g1[g_pos_3] * fc3_normal_squared[g_pos[i][3]] * triplet_weight;
for (j = 0; j < num_temps; j++) {
if (n1[j * num_band + g_pos[i][1]] < 0 ||
n2[j * num_band + g_pos[i][2]] < 0) {
;
} else {
if (temperatures[j] > 0) {
imag_self_energy[j * num_band0 + g_pos[i][0]] +=
((n1[j * num_band + g_pos[i][1]] +
n2[j * num_band + g_pos[i][2]] + 1) *
g1[g_pos_3] +
(n1[j * num_band + g_pos[i][1]] -
n2[j * num_band + g_pos[i][2]]) *
g2_3[g_pos_3]) *
fc3_normal_squared[g_pos[i][3]] * triplet_weight;
} else {
imag_self_energy[j * num_band0 + g_pos[i][0]] +=
g1[g_pos_3] * fc3_normal_squared[g_pos[i][3]] *
triplet_weight;
}
}
}
}
}
}
free(n1);
n1 = NULL;
free(n2);
n2 = NULL;
free(n1);
n1 = NULL;
free(n2);
n2 = NULL;
}
long ise_set_g_pos(long (*g_pos)[4],
const long num_band0,
const long num_band,
const char *g_zero)
{
long num_g_pos, j, k, l, jkl;
long ise_set_g_pos(long (*g_pos)[4], const long num_band0, const long num_band,
const char *g_zero) {
long num_g_pos, j, k, l, jkl;
num_g_pos = 0;
jkl = 0;
for (j = 0; j < num_band0; j++)
{
for (k = 0; k < num_band; k++)
{
for (l = 0; l < num_band; l++)
{
if (!g_zero[jkl])
{
g_pos[num_g_pos][0] = j;
g_pos[num_g_pos][1] = k;
g_pos[num_g_pos][2] = l;
g_pos[num_g_pos][3] = jkl;
num_g_pos++;
num_g_pos = 0;
jkl = 0;
for (j = 0; j < num_band0; j++) {
for (k = 0; k < num_band; k++) {
for (l = 0; l < num_band; l++) {
if (!g_zero[jkl]) {
g_pos[num_g_pos][0] = j;
g_pos[num_g_pos][1] = k;
g_pos[num_g_pos][2] = l;
g_pos[num_g_pos][3] = jkl;
num_g_pos++;
}
jkl++;
}
}
jkl++;
}
}
}
return num_g_pos;
return num_g_pos;
}
static long ise_set_g_pos_frequency_point(long (*g_pos)[4],
const long num_band0,
const long num_band,
const char *g_zero)
{
long num_g_pos, j, k, l, kl, jkl;
const char *g_zero) {
long num_g_pos, j, k, l, kl, jkl;
num_g_pos = 0;
jkl = 0;
for (j = 0; j < num_band0; j++)
{
kl = 0;
for (k = 0; k < num_band; k++)
{
for (l = 0; l < num_band; l++)
{
if (!g_zero[kl])
{
g_pos[num_g_pos][0] = j;
g_pos[num_g_pos][1] = k;
g_pos[num_g_pos][2] = l;
g_pos[num_g_pos][3] = jkl;
num_g_pos++;
num_g_pos = 0;
jkl = 0;
for (j = 0; j < num_band0; j++) {
kl = 0;
for (k = 0; k < num_band; k++) {
for (l = 0; l < num_band; l++) {
if (!g_zero[kl]) {
g_pos[num_g_pos][0] = j;
g_pos[num_g_pos][1] = k;
g_pos[num_g_pos][2] = l;
g_pos[num_g_pos][3] = jkl;
num_g_pos++;
}
jkl++;
kl++;
}
}
jkl++;
kl++;
}
}
}
return num_g_pos;
return num_g_pos;
}
static void
detailed_imag_self_energy_at_triplet(double *detailed_imag_self_energy,
double *imag_self_energy,
const long num_band0,
const long num_band,
const double *fc3_normal_squared,
const double *frequencies,
const long triplet[3],
const double *g1,
const double *g2_3,
const char *g_zero,
const double *temperatures,
const long num_temps,
const double cutoff_frequency)
{
long i, j, adrs_shift;
double *n1, *n2;
static void detailed_imag_self_energy_at_triplet(
double *detailed_imag_self_energy, double *imag_self_energy,
const long num_band0, const long num_band, const double *fc3_normal_squared,
const double *frequencies, const long triplet[3], const double *g1,
const double *g2_3, const char *g_zero, const double *temperatures,
const long num_temps, const double cutoff_frequency) {
long i, j, adrs_shift;
double *n1, *n2;
n1 = NULL;
n2 = NULL;
n1 = NULL;
n2 = NULL;
n1 = (double *)malloc(sizeof(double) * num_band);
n2 = (double *)malloc(sizeof(double) * num_band);
n1 = (double *)malloc(sizeof(double) * num_band);
n2 = (double *)malloc(sizeof(double) * num_band);
for (i = 0; i < num_temps; i++)
{
set_occupations(n1,
n2,
num_band,
temperatures[i],
triplet,
frequencies,
cutoff_frequency);
for (i = 0; i < num_temps; i++) {
set_occupations(n1, n2, num_band, temperatures[i], triplet, frequencies,
cutoff_frequency);
for (j = 0; j < num_band0; j++)
{
adrs_shift = j * num_band * num_band;
if (temperatures[i] > 0)
{
imag_self_energy[i * num_band0 + j] =
collect_detailed_imag_self_energy(detailed_imag_self_energy + adrs_shift,
num_band,
fc3_normal_squared + adrs_shift,
n1,
n2,
g1 + adrs_shift,
g2_3 + adrs_shift,
g_zero + adrs_shift);
}
else
{
imag_self_energy[i * num_band0 + j] =
collect_detailed_imag_self_energy_0K(detailed_imag_self_energy + adrs_shift,
num_band,
fc3_normal_squared + adrs_shift,
n1,
n2,
g1 + adrs_shift,
g_zero + adrs_shift);
}
for (j = 0; j < num_band0; j++) {
adrs_shift = j * num_band * num_band;
if (temperatures[i] > 0) {
imag_self_energy[i * num_band0 + j] =
collect_detailed_imag_self_energy(
detailed_imag_self_energy + adrs_shift, num_band,
fc3_normal_squared + adrs_shift, n1, n2,
g1 + adrs_shift, g2_3 + adrs_shift,
g_zero + adrs_shift);
} else {
imag_self_energy[i * num_band0 + j] =
collect_detailed_imag_self_energy_0K(
detailed_imag_self_energy + adrs_shift, num_band,
fc3_normal_squared + adrs_shift, n1, n2,
g1 + adrs_shift, g_zero + adrs_shift);
}
}
}
}
free(n1);
n1 = NULL;
free(n2);
n2 = NULL;
free(n1);
n1 = NULL;
free(n2);
n2 = NULL;
}
static double
collect_detailed_imag_self_energy(double *imag_self_energy,
const long num_band,
const double *fc3_normal_squared,
const double *n1,
const double *n2,
const double *g1,
const double *g2_3,
const char *g_zero)
{
long ij, i, j;
double sum_g;
static double collect_detailed_imag_self_energy(
double *imag_self_energy, const long num_band,
const double *fc3_normal_squared, const double *n1, const double *n2,
const double *g1, const double *g2_3, const char *g_zero) {
long ij, i, j;
double sum_g;
sum_g = 0;
for (ij = 0; ij < num_band * num_band; ij++)
{
imag_self_energy[ij] = 0;
if (g_zero[ij])
{
continue;
sum_g = 0;
for (ij = 0; ij < num_band * num_band; ij++) {
imag_self_energy[ij] = 0;
if (g_zero[ij]) {
continue;
}
i = ij / num_band;
j = ij % num_band;
if (n1[i] < 0 || n2[j] < 0) {
continue;
}
imag_self_energy[ij] =
(((n1[i] + n2[j] + 1) * g1[ij] + (n1[i] - n2[j]) * g2_3[ij]) *
fc3_normal_squared[ij]);
sum_g += imag_self_energy[ij];
}
i = ij / num_band;
j = ij % num_band;
if (n1[i] < 0 || n2[j] < 0)
{
continue;
}
imag_self_energy[ij] = (((n1[i] + n2[j] + 1) * g1[ij] +
(n1[i] - n2[j]) * g2_3[ij]) *
fc3_normal_squared[ij]);
sum_g += imag_self_energy[ij];
}
return sum_g;
return sum_g;
}
static double
collect_detailed_imag_self_energy_0K(double *imag_self_energy,
const long num_band,
const double *fc3_normal_squared,
const double *n1,
const double *n2,
const double *g1,
const char *g_zero)
{
long ij, i, j;
double sum_g;
static double collect_detailed_imag_self_energy_0K(
double *imag_self_energy, const long num_band,
const double *fc3_normal_squared, const double *n1, const double *n2,
const double *g1, const char *g_zero) {
long ij, i, j;
double sum_g;
sum_g = 0;
for (ij = 0; ij < num_band * num_band; ij++)
{
imag_self_energy[ij] = 0;
if (g_zero[ij])
{
continue;
sum_g = 0;
for (ij = 0; ij < num_band * num_band; ij++) {
imag_self_energy[ij] = 0;
if (g_zero[ij]) {
continue;
}
i = ij / num_band;
j = ij % num_band;
if (n1[i] < 0 || n2[j] < 0) {
continue;
}
imag_self_energy[ij] = g1[ij] * fc3_normal_squared[ij];
sum_g += imag_self_energy[ij];
}
i = ij / num_band;
j = ij % num_band;
if (n1[i] < 0 || n2[j] < 0)
{
continue;
}
imag_self_energy[ij] = g1[ij] * fc3_normal_squared[ij];
sum_g += imag_self_energy[ij];
}
return sum_g;
return sum_g;
}
static void set_occupations(double *n1,
double *n2,
const long num_band,
const double temperature,
const long triplet[3],
static void set_occupations(double *n1, double *n2, const long num_band,
const double temperature, const long triplet[3],
const double *frequencies,
const double cutoff_frequency)
{
long j;
double f1, f2;
const double cutoff_frequency) {
long j;
double f1, f2;
for (j = 0; j < num_band; j++)
{
f1 = frequencies[triplet[1] * num_band + j];
f2 = frequencies[triplet[2] * num_band + j];
if (f1 > cutoff_frequency)
{
n1[j] = phonoc_bose_einstein(f1, temperature);
for (j = 0; j < num_band; j++) {
f1 = frequencies[triplet[1] * num_band + j];
f2 = frequencies[triplet[2] * num_band + j];
if (f1 > cutoff_frequency) {
n1[j] = phonoc_bose_einstein(f1, temperature);
} else {
n1[j] = -1;
}
if (f2 > cutoff_frequency) {
n2[j] = phonoc_bose_einstein(f2, temperature);
} else {
n2[j] = -1;
}
}
else
{
n1[j] = -1;
}
if (f2 > cutoff_frequency)
{
n2[j] = phonoc_bose_einstein(f2, temperature);
}
else
{
n2[j] = -1;
}
}
}

View File

@ -36,50 +36,31 @@
#define __imag_self_energy_with_g_H__
#include <stddef.h>
#include "phonoc_array.h"
void ise_get_imag_self_energy_at_bands_with_g(double *imag_self_energy,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const double *g,
const char *g_zero,
const double temperature,
const double cutoff_frequency,
const long num_frequency_points,
const long frequency_point_index);
void ise_get_detailed_imag_self_energy_at_bands_with_g(double *detailed_imag_self_energy,
double *imag_self_energy_N,
double *imag_self_energy_U,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const long (*bz_grid_addresses)[3],
const double *g,
const char *g_zero,
const double temperature,
const double cutoff_frequency);
void ise_imag_self_energy_at_triplet(double *imag_self_energy,
const long num_band0,
const long num_band,
const double *fc3_normal_squared,
const double *frequencies,
const long triplet[3],
const long triplet_weight,
const double *g1,
const double *g2_3,
const long (*g_pos)[4],
const long num_g_pos,
const double *temperatures,
const long num_temps,
const double cutoff_frequency,
const long openmp_at_bands,
const long at_a_frequency_point);
long ise_set_g_pos(long (*g_pos)[4],
const long num_band0,
const long num_band,
void ise_get_imag_self_energy_at_bands_with_g(
double *imag_self_energy, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplet_weights, const double *g, const char *g_zero,
const double temperature, const double cutoff_frequency,
const long num_frequency_points, const long frequency_point_index);
void ise_get_detailed_imag_self_energy_at_bands_with_g(
double *detailed_imag_self_energy, double *imag_self_energy_N,
double *imag_self_energy_U, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplet_weights, const long (*bz_grid_addresses)[3],
const double *g, const char *g_zero, const double temperature,
const double cutoff_frequency);
void ise_imag_self_energy_at_triplet(
double *imag_self_energy, const long num_band0, const long num_band,
const double *fc3_normal_squared, const double *frequencies,
const long triplet[3], const long triplet_weight, const double *g1,
const double *g2_3, const long (*g_pos)[4], const long num_g_pos,
const double *temperatures, const long num_temps,
const double cutoff_frequency, const long openmp_at_bands,
const long at_a_frequency_point);
long ise_set_g_pos(long (*g_pos)[4], const long num_band0, const long num_band,
const char *g_zero);
#endif

View File

@ -32,418 +32,250 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include "interaction.h"
#include <stdio.h>
#include <stdlib.h>
#include "bzgrid.h"
#include "interaction.h"
#include "imag_self_energy_with_g.h"
#include "lapack_wrapper.h"
#include "phonoc_array.h"
#include "real_to_reciprocal.h"
#include "reciprocal_to_normal.h"
#include "lapack_wrapper.h"
static const long index_exchange[6][3] = {{0, 1, 2},
{2, 0, 1},
{1, 2, 0},
{2, 1, 0},
{0, 2, 1},
{1, 0, 2}};
static void real_to_normal(double *fc3_normal_squared,
const long (*g_pos)[4],
const long num_g_pos,
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 double *fc3,
const long is_compact_fc3,
const double q_vecs[3][3], /* q0, q1, q2 */
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const long *band_indices,
const long num_band,
const double cutoff_frequency,
const long triplet_index,
const long num_triplets,
const long openmp_at_bands);
static void real_to_normal_sym_q(double *fc3_normal_squared,
const long (*g_pos)[4],
const long num_g_pos,
double *const freqs[3],
lapack_complex_double *const eigvecs[3],
const double *fc3,
const long is_compact_fc3,
const double q_vecs[3][3], /* q0, q1, q2 */
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const long *band_indices,
const long num_band0,
const long num_band,
const double cutoff_frequency,
const long triplet_index,
const long num_triplets,
const long openmp_at_bands);
static const long index_exchange[6][3] = {{0, 1, 2}, {2, 0, 1}, {1, 2, 0},
{2, 1, 0}, {0, 2, 1}, {1, 0, 2}};
static void real_to_normal(
double *fc3_normal_squared, const long (*g_pos)[4], const long num_g_pos,
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 double *fc3,
const long is_compact_fc3, const double q_vecs[3][3], /* q0, q1, q2 */
const double (*svecs)[3], const long multi_dims[2],
const long (*multiplicity)[2], const double *masses, const long *p2s_map,
const long *s2p_map, const long *band_indices, const long num_band,
const double cutoff_frequency, const long triplet_index,
const long num_triplets, const long openmp_at_bands);
static void real_to_normal_sym_q(
double *fc3_normal_squared, const long (*g_pos)[4], const long num_g_pos,
double *const freqs[3], lapack_complex_double *const eigvecs[3],
const double *fc3, const long is_compact_fc3,
const double q_vecs[3][3], /* q0, q1, q2 */
const double (*svecs)[3], const long multi_dims[2],
const long (*multiplicity)[2], const double *masses, const long *p2s_map,
const long *s2p_map, const long *band_indices, const long num_band0,
const long num_band, const double cutoff_frequency,
const long triplet_index, const long num_triplets,
const long openmp_at_bands);
/* fc3_normal_squared[num_triplets, num_band0, num_band, num_band] */
void itr_get_interaction(Darray *fc3_normal_squared,
const char *g_zero,
void itr_get_interaction(Darray *fc3_normal_squared, const char *g_zero,
const Darray *frequencies,
const lapack_complex_double *eigenvectors,
const long (*triplets)[3],
const long num_triplets,
const ConstBZGrid *bzgrid,
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long (*triplets)[3], const long num_triplets,
const ConstBZGrid *bzgrid, const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const long *band_indices,
const long symmetrize_fc3_q,
const double cutoff_frequency)
{
long openmp_per_triplets;
long(*g_pos)[4];
long i;
long num_band, num_band0, num_band_prod, num_g_pos;
const long (*multiplicity)[2], const double *masses,
const long *p2s_map, const long *s2p_map,
const long *band_indices, const long symmetrize_fc3_q,
const double cutoff_frequency) {
long openmp_per_triplets;
long(*g_pos)[4];
long i;
long num_band, num_band0, num_band_prod, num_g_pos;
g_pos = NULL;
g_pos = NULL;
num_band0 = fc3_normal_squared->dims[1];
num_band = frequencies->dims[1];
num_band_prod = num_band0 * num_band * num_band;
num_band0 = fc3_normal_squared->dims[1];
num_band = frequencies->dims[1];
num_band_prod = num_band0 * num_band * num_band;
if (num_triplets > num_band)
{
openmp_per_triplets = 1;
}
else
{
openmp_per_triplets = 0;
}
if (num_triplets > num_band) {
openmp_per_triplets = 1;
} else {
openmp_per_triplets = 0;
}
#ifdef PHPYOPENMP
#pragma omp parallel for schedule(guided) private(num_g_pos, g_pos) if (openmp_per_triplets)
#pragma omp parallel for schedule(guided) private( \
num_g_pos, g_pos) if (openmp_per_triplets)
#endif
for (i = 0; i < num_triplets; i++)
{
g_pos = (long(*)[4])malloc(sizeof(long[4]) * num_band_prod);
num_g_pos = ise_set_g_pos(g_pos,
num_band0,
num_band,
g_zero + i * num_band_prod);
for (i = 0; i < num_triplets; i++) {
g_pos = (long(*)[4])malloc(sizeof(long[4]) * num_band_prod);
num_g_pos = ise_set_g_pos(g_pos, num_band0, num_band,
g_zero + i * num_band_prod);
itr_get_interaction_at_triplet(
fc3_normal_squared->data + i * num_band_prod,
num_band0,
num_band,
g_pos,
num_g_pos,
frequencies->data,
eigenvectors,
triplets[i],
bzgrid,
fc3,
is_compact_fc3,
svecs,
multi_dims,
multiplicity,
masses,
p2s_map,
s2p_map,
band_indices,
symmetrize_fc3_q,
cutoff_frequency,
i,
num_triplets,
1 - openmp_per_triplets);
itr_get_interaction_at_triplet(
fc3_normal_squared->data + i * num_band_prod, num_band0, num_band,
g_pos, num_g_pos, frequencies->data, eigenvectors, triplets[i],
bzgrid, fc3, is_compact_fc3, svecs, multi_dims, multiplicity,
masses, p2s_map, s2p_map, band_indices, symmetrize_fc3_q,
cutoff_frequency, i, num_triplets, 1 - openmp_per_triplets);
free(g_pos);
g_pos = NULL;
}
free(g_pos);
g_pos = NULL;
}
}
void itr_get_interaction_at_triplet(double *fc3_normal_squared,
const long num_band0,
const long num_band,
const long (*g_pos)[4],
const long num_g_pos,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long triplet[3],
const ConstBZGrid *bzgrid,
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const long *band_indices,
const long symmetrize_fc3_q,
const double cutoff_frequency,
const long triplet_index, /* only for print */
const long num_triplets, /* only for print */
const long openmp_at_bands)
{
long j, k;
double *freqs[3];
lapack_complex_double *eigvecs[3];
double q_vecs[3][3];
void itr_get_interaction_at_triplet(
double *fc3_normal_squared, const long num_band0, const long num_band,
const long (*g_pos)[4], const long num_g_pos, const double *frequencies,
const lapack_complex_double *eigenvectors, const long triplet[3],
const ConstBZGrid *bzgrid, const double *fc3, const long is_compact_fc3,
const double (*svecs)[3], const long multi_dims[2],
const long (*multiplicity)[2], const double *masses, const long *p2s_map,
const long *s2p_map, const long *band_indices, const long symmetrize_fc3_q,
const double cutoff_frequency,
const long triplet_index, /* only for print */
const long num_triplets, /* only for print */
const long openmp_at_bands) {
long j, k;
double *freqs[3];
lapack_complex_double *eigvecs[3];
double q_vecs[3][3];
for (j = 0; j < 3; j++)
{
for (k = 0; k < 3; k++)
{
q_vecs[j][k] = ((double)bzgrid->addresses[triplet[j]][k]) / bzgrid->D_diag[k];
for (j = 0; j < 3; j++) {
for (k = 0; k < 3; k++) {
q_vecs[j][k] =
((double)bzgrid->addresses[triplet[j]][k]) / bzgrid->D_diag[k];
}
bzg_multiply_matrix_vector_ld3(q_vecs[j], bzgrid->Q, q_vecs[j]);
}
bzg_multiply_matrix_vector_ld3(q_vecs[j], bzgrid->Q, q_vecs[j]);
}
if (symmetrize_fc3_q)
{
for (j = 0; j < 3; j++)
{
freqs[j] = (double *)malloc(sizeof(double) * num_band);
eigvecs[j] = (lapack_complex_double *)
malloc(sizeof(lapack_complex_double) * num_band * num_band);
for (k = 0; k < num_band; k++)
{
freqs[j][k] = frequencies[triplet[j] * num_band + k];
}
for (k = 0; k < num_band * num_band; k++)
{
eigvecs[j][k] = eigenvectors[triplet[j] * num_band * num_band + k];
}
if (symmetrize_fc3_q) {
for (j = 0; j < 3; j++) {
freqs[j] = (double *)malloc(sizeof(double) * num_band);
eigvecs[j] = (lapack_complex_double *)malloc(
sizeof(lapack_complex_double) * num_band * num_band);
for (k = 0; k < num_band; k++) {
freqs[j][k] = frequencies[triplet[j] * num_band + k];
}
for (k = 0; k < num_band * num_band; k++) {
eigvecs[j][k] =
eigenvectors[triplet[j] * num_band * num_band + k];
}
}
real_to_normal_sym_q(
fc3_normal_squared, g_pos, num_g_pos, freqs, eigvecs, fc3,
is_compact_fc3, q_vecs, /* q0, q1, q2 */
svecs, multi_dims, multiplicity, masses, p2s_map, s2p_map,
band_indices, num_band0, num_band, cutoff_frequency, triplet_index,
num_triplets, openmp_at_bands);
for (j = 0; j < 3; j++) {
free(freqs[j]);
freqs[j] = NULL;
free(eigvecs[j]);
eigvecs[j] = NULL;
}
} else {
real_to_normal(fc3_normal_squared, g_pos, num_g_pos,
frequencies + triplet[0] * num_band,
frequencies + triplet[1] * num_band,
frequencies + triplet[2] * num_band,
eigenvectors + triplet[0] * num_band * num_band,
eigenvectors + triplet[1] * num_band * num_band,
eigenvectors + triplet[2] * num_band * num_band, fc3,
is_compact_fc3, q_vecs, /* q0, q1, q2 */
svecs, multi_dims, multiplicity, masses, p2s_map,
s2p_map, band_indices, num_band, cutoff_frequency,
triplet_index, num_triplets, openmp_at_bands);
}
real_to_normal_sym_q(fc3_normal_squared,
g_pos,
num_g_pos,
freqs,
eigvecs,
fc3,
is_compact_fc3,
q_vecs, /* q0, q1, q2 */
svecs,
multi_dims,
multiplicity,
masses,
p2s_map,
s2p_map,
band_indices,
num_band0,
num_band,
cutoff_frequency,
triplet_index,
num_triplets,
openmp_at_bands);
for (j = 0; j < 3; j++)
{
free(freqs[j]);
freqs[j] = NULL;
free(eigvecs[j]);
eigvecs[j] = NULL;
}
}
else
{
real_to_normal(fc3_normal_squared,
g_pos,
num_g_pos,
frequencies + triplet[0] * num_band,
frequencies + triplet[1] * num_band,
frequencies + triplet[2] * num_band,
eigenvectors + triplet[0] * num_band * num_band,
eigenvectors + triplet[1] * num_band * num_band,
eigenvectors + triplet[2] * num_band * num_band,
fc3,
is_compact_fc3,
q_vecs, /* q0, q1, q2 */
svecs,
multi_dims,
multiplicity,
masses,
p2s_map,
s2p_map,
band_indices,
num_band,
cutoff_frequency,
triplet_index,
num_triplets,
openmp_at_bands);
}
}
static void real_to_normal(double *fc3_normal_squared,
const long (*g_pos)[4],
const long num_g_pos,
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 double *fc3,
const long is_compact_fc3,
const double q_vecs[3][3], /* q0, q1, q2 */
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const long *band_indices,
const long num_band,
const double cutoff_frequency,
const long triplet_index,
const long num_triplets,
const long openmp_at_bands)
{
lapack_complex_double *fc3_reciprocal;
static void real_to_normal(
double *fc3_normal_squared, const long (*g_pos)[4], const long num_g_pos,
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 double *fc3,
const long is_compact_fc3, const double q_vecs[3][3], /* q0, q1, q2 */
const double (*svecs)[3], const long multi_dims[2],
const long (*multiplicity)[2], const double *masses, const long *p2s_map,
const long *s2p_map, const long *band_indices, const long num_band,
const double cutoff_frequency, const long triplet_index,
const long num_triplets, const long openmp_at_bands) {
lapack_complex_double *fc3_reciprocal;
fc3_reciprocal =
(lapack_complex_double *)malloc(sizeof(lapack_complex_double) *
num_band * num_band * num_band);
r2r_real_to_reciprocal(fc3_reciprocal,
q_vecs,
fc3,
is_compact_fc3,
svecs,
multi_dims,
multiplicity,
p2s_map,
s2p_map,
openmp_at_bands);
fc3_reciprocal = (lapack_complex_double *)malloc(
sizeof(lapack_complex_double) * num_band * num_band * num_band);
r2r_real_to_reciprocal(fc3_reciprocal, q_vecs, fc3, is_compact_fc3, svecs,
multi_dims, multiplicity, p2s_map, s2p_map,
openmp_at_bands);
#ifdef MEASURE_R2N
if (openmp_at_bands && num_triplets > 0)
{
printf("At triplet %d/%d (# of bands=%d):\n",
triplet_index, num_triplets, num_band0);
}
if (openmp_at_bands && num_triplets > 0) {
printf("At triplet %d/%d (# of bands=%d):\n", triplet_index,
num_triplets, num_band0);
}
#endif
reciprocal_to_normal_squared(fc3_normal_squared,
g_pos,
num_g_pos,
fc3_reciprocal,
freqs0,
freqs1,
freqs2,
eigvecs0,
eigvecs1,
eigvecs2,
masses,
band_indices,
num_band,
cutoff_frequency,
openmp_at_bands);
reciprocal_to_normal_squared(
fc3_normal_squared, g_pos, num_g_pos, fc3_reciprocal, freqs0, freqs1,
freqs2, eigvecs0, eigvecs1, eigvecs2, masses, band_indices, num_band,
cutoff_frequency, openmp_at_bands);
free(fc3_reciprocal);
fc3_reciprocal = NULL;
free(fc3_reciprocal);
fc3_reciprocal = NULL;
}
static void real_to_normal_sym_q(double *fc3_normal_squared,
const long (*g_pos)[4],
const long num_g_pos,
double *const freqs[3],
lapack_complex_double *const eigvecs[3],
const double *fc3,
const long is_compact_fc3,
const double q_vecs[3][3], /* q0, q1, q2 */
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const long *band_indices,
const long num_band0,
const long num_band,
const double cutoff_frequency,
const long triplet_index,
const long num_triplets,
const long openmp_at_bands)
{
long i, j, k, l;
long band_ex[3];
double q_vecs_ex[3][3];
double *fc3_normal_squared_ex;
static void real_to_normal_sym_q(
double *fc3_normal_squared, const long (*g_pos)[4], const long num_g_pos,
double *const freqs[3], lapack_complex_double *const eigvecs[3],
const double *fc3, const long is_compact_fc3,
const double q_vecs[3][3], /* q0, q1, q2 */
const double (*svecs)[3], const long multi_dims[2],
const long (*multiplicity)[2], const double *masses, const long *p2s_map,
const long *s2p_map, const long *band_indices, const long num_band0,
const long num_band, const double cutoff_frequency,
const long triplet_index, const long num_triplets,
const long openmp_at_bands) {
long i, j, k, l;
long band_ex[3];
double q_vecs_ex[3][3];
double *fc3_normal_squared_ex;
fc3_normal_squared_ex =
(double *)malloc(sizeof(double) * num_band * num_band * num_band);
fc3_normal_squared_ex =
(double *)malloc(sizeof(double) * num_band * num_band * num_band);
for (i = 0; i < num_band0 * num_band * num_band; i++)
{
fc3_normal_squared[i] = 0;
}
for (i = 0; i < 6; i++)
{
for (j = 0; j < 3; j++)
{
for (k = 0; k < 3; k++)
{
q_vecs_ex[j][k] = q_vecs[index_exchange[i][j]][k];
}
for (i = 0; i < num_band0 * num_band * num_band; i++) {
fc3_normal_squared[i] = 0;
}
real_to_normal(fc3_normal_squared_ex,
g_pos,
num_g_pos,
freqs[index_exchange[i][0]],
freqs[index_exchange[i][1]],
freqs[index_exchange[i][2]],
eigvecs[index_exchange[i][0]],
eigvecs[index_exchange[i][1]],
eigvecs[index_exchange[i][2]],
fc3,
is_compact_fc3,
q_vecs_ex, /* q0, q1, q2 */
svecs,
multi_dims,
multiplicity,
masses,
p2s_map,
s2p_map,
band_indices,
num_band,
cutoff_frequency,
triplet_index,
num_triplets,
openmp_at_bands);
for (j = 0; j < num_band0; j++)
{
for (k = 0; k < num_band; k++)
{
for (l = 0; l < num_band; l++)
{
band_ex[0] = band_indices[j];
band_ex[1] = k;
band_ex[2] = l;
fc3_normal_squared[j * num_band * num_band +
k * num_band +
l] +=
fc3_normal_squared_ex[band_ex[index_exchange[i][0]] *
num_band * num_band +
band_ex[index_exchange[i][1]] * num_band +
band_ex[index_exchange[i][2]]] /
6;
for (i = 0; i < 6; i++) {
for (j = 0; j < 3; j++) {
for (k = 0; k < 3; k++) {
q_vecs_ex[j][k] = q_vecs[index_exchange[i][j]][k];
}
}
real_to_normal(
fc3_normal_squared_ex, g_pos, num_g_pos,
freqs[index_exchange[i][0]], freqs[index_exchange[i][1]],
freqs[index_exchange[i][2]], eigvecs[index_exchange[i][0]],
eigvecs[index_exchange[i][1]], eigvecs[index_exchange[i][2]], fc3,
is_compact_fc3, q_vecs_ex, /* q0, q1, q2 */
svecs, multi_dims, multiplicity, masses, p2s_map, s2p_map,
band_indices, num_band, cutoff_frequency, triplet_index,
num_triplets, openmp_at_bands);
for (j = 0; j < num_band0; j++) {
for (k = 0; k < num_band; k++) {
for (l = 0; l < num_band; l++) {
band_ex[0] = band_indices[j];
band_ex[1] = k;
band_ex[2] = l;
fc3_normal_squared[j * num_band * num_band + k * num_band +
l] +=
fc3_normal_squared_ex[band_ex[index_exchange[i][0]] *
num_band * num_band +
band_ex[index_exchange[i][1]] *
num_band +
band_ex[index_exchange[i][2]]] /
6;
}
}
}
}
}
}
free(fc3_normal_squared_ex);
free(fc3_normal_squared_ex);
}

View File

@ -39,46 +39,28 @@
#include "lapack_wrapper.h"
#include "phonoc_array.h"
void itr_get_interaction(Darray *fc3_normal_squared,
const char *g_zero,
void itr_get_interaction(Darray *fc3_normal_squared, const char *g_zero,
const Darray *frequencies,
const lapack_complex_double *eigenvectors,
const long (*triplets)[3],
const long num_triplets,
const ConstBZGrid *bzgrid,
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long (*triplets)[3], const long num_triplets,
const ConstBZGrid *bzgrid, const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const long *band_indices,
const long symmetrize_fc3_q,
const long (*multiplicity)[2], const double *masses,
const long *p2s_map, const long *s2p_map,
const long *band_indices, const long symmetrize_fc3_q,
const double cutoff_frequency);
void itr_get_interaction_at_triplet(double *fc3_normal_squared,
const long num_band0,
const long num_band,
const long (*g_pos)[4],
const long num_g_pos,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long triplet[3],
const ConstBZGrid *bzgrid,
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const long *band_indices,
const long symmetrize_fc3_q,
const double cutoff_frequency,
const long triplet_index, /* only for print */
const long num_triplets, /* only for print */
const long openmp_at_bands);
void itr_get_interaction_at_triplet(
double *fc3_normal_squared, const long num_band0, const long num_band,
const long (*g_pos)[4], const long num_g_pos, const double *frequencies,
const lapack_complex_double *eigenvectors, const long triplet[3],
const ConstBZGrid *bzgrid, const double *fc3, const long is_compact_fc3,
const double (*svecs)[3], const long multi_dims[2],
const long (*multiplicity)[2], const double *masses, const long *p2s_map,
const long *s2p_map, const long *band_indices, const long symmetrize_fc3_q,
const double cutoff_frequency,
const long triplet_index, /* only for print */
const long num_triplets, /* only for print */
const long openmp_at_bands);
#endif

View File

@ -32,224 +32,196 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include "isotope.h"
#include <stdlib.h>
#include "lapack_wrapper.h"
#include "phonoc_const.h"
#include "phonoc_utils.h"
#include "isotope.h"
#include "lapack_wrapper.h"
void iso_get_isotope_scattering_strength(double *gamma,
const long grid_point,
const double *mass_variances,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long num_grid_points,
const long *band_indices,
const long num_band,
const long num_band0,
const double sigma,
const double cutoff_frequency)
{
long i, j, k, l, m;
double *e0_r, *e0_i, e1_r, e1_i, a, b, f, *f0, dist, sum_g, sum_g_k;
void iso_get_isotope_scattering_strength(
double *gamma, const long grid_point, const double *mass_variances,
const double *frequencies, const lapack_complex_double *eigenvectors,
const long num_grid_points, const long *band_indices, const long num_band,
const long num_band0, const double sigma, const double cutoff_frequency) {
long i, j, k, l, m;
double *e0_r, *e0_i, e1_r, e1_i, a, b, f, *f0, dist, sum_g, sum_g_k;
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);
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);
for (i = 0; i < num_band0; i++)
{
f0[i] = frequencies[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_band0; i++) {
f0[i] = frequencies[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_band0; i++)
{
gamma[i] = 0;
}
for (i = 0; i < num_band0; i++)
{ /* band index0 */
if (f0[i] < cutoff_frequency)
{
continue;
for (i = 0; i < num_band0; i++) {
gamma[i] = 0;
}
sum_g = 0;
for (i = 0; i < num_band0; i++) { /* band index0 */
if (f0[i] < cutoff_frequency) {
continue;
}
sum_g = 0;
#ifdef PHPYOPENMP
#pragma omp parallel for private(k, l, m, f, e1_r, e1_i, a, b, dist, sum_g_k) reduction(+ \
: sum_g)
#endif
for (j = 0; j < num_grid_points; j++)
{
sum_g_k = 0;
for (k = 0; k < num_band; k++)
{ /* band index */
f = frequencies[j * num_band + k];
if (f < cutoff_frequency)
{
continue;
for (j = 0; j < num_grid_points; j++) {
sum_g_k = 0;
for (k = 0; k < num_band; k++) { /* band index */
f = frequencies[j * num_band + k];
if (f < cutoff_frequency) {
continue;
}
dist = phonoc_gaussian(f - f0[i], sigma);
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[j * num_band * num_band +
(l * 3 + m) * num_band + k]);
e1_i = lapack_complex_double_imag(
eigenvectors[j * num_band * num_band +
(l * 3 + m) * num_band + k]);
a += (e0_r[i * num_band + l * 3 + m] * e1_r +
e0_i[i * num_band + l * 3 + m] * e1_i);
b += (e0_i[i * num_band + l * 3 + m] * e1_r -
e0_r[i * num_band + l * 3 + m] * e1_i);
}
sum_g_k += (a * a + b * b) * mass_variances[l] * dist;
}
}
sum_g += sum_g_k;
}
dist = phonoc_gaussian(f - f0[i], sigma);
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[j * num_band * num_band +
(l * 3 + m) * num_band + k]);
e1_i = lapack_complex_double_imag(eigenvectors[j * num_band * num_band +
(l * 3 + m) * num_band + k]);
a += (e0_r[i * num_band + l * 3 + m] * e1_r +
e0_i[i * num_band + l * 3 + m] * e1_i);
b += (e0_i[i * num_band + l * 3 + m] * e1_r -
e0_r[i * num_band + l * 3 + m] * e1_i);
}
sum_g_k += (a * a + b * b) * mass_variances[l] * dist;
}
}
sum_g += sum_g_k;
gamma[i] = sum_g;
}
gamma[i] = sum_g;
}
for (i = 0; i < num_band0; i++)
{
/* Frequency unit to ang-freq: *(2pi)**2/(2pi) */
/* Ang-freq to freq unit (for lifetime): /2pi */
/* gamma = 1/2t */
gamma[i] *= M_2PI / 4 * f0[i] * f0[i] / 2;
}
for (i = 0; i < num_band0; i++) {
/* Frequency unit to ang-freq: *(2pi)**2/(2pi) */
/* Ang-freq to freq unit (for lifetime): /2pi */
/* gamma = 1/2t */
gamma[i] *= M_2PI / 4 * f0[i] * f0[i] / 2;
}
free(f0);
f0 = NULL;
free(e0_r);
e0_r = NULL;
free(e0_i);
e0_i = NULL;
free(f0);
f0 = NULL;
free(e0_r);
e0_r = NULL;
free(e0_i);
e0_i = NULL;
}
void iso_get_thm_isotope_scattering_strength(double *gamma,
const long grid_point,
const long *ir_grid_points,
const long *weights,
const double *mass_variances,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long num_grid_points,
const long *band_indices,
const long num_band,
const long num_band0,
const double *integration_weights,
const double cutoff_frequency)
{
long i, j, k, l, m, gp;
double *e0_r, *e0_i, *f0, *gamma_ij;
double e1_r, e1_i, a, b, f, dist, sum_g_k;
void iso_get_thm_isotope_scattering_strength(
double *gamma, const long grid_point, const long *ir_grid_points,
const long *weights, const double *mass_variances,
const double *frequencies, const lapack_complex_double *eigenvectors,
const long num_grid_points, const long *band_indices, const long num_band,
const long num_band0, const double *integration_weights,
const double cutoff_frequency) {
long i, j, k, l, m, gp;
double *e0_r, *e0_i, *f0, *gamma_ij;
double e1_r, e1_i, a, b, f, dist, sum_g_k;
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);
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);
for (i = 0; i < num_band0; i++)
{
f0[i] = frequencies[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_band0; i++) {
f0[i] = frequencies[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]]);
}
}
}
gamma_ij = (double *)malloc(sizeof(double) * num_grid_points * num_band0);
gamma_ij = (double *)malloc(sizeof(double) * num_grid_points * num_band0);
#ifdef PHPYOPENMP
#pragma omp parallel for
#endif
for (i = 0; i < num_grid_points * num_band0; i++)
{
gamma_ij[i] = 0;
}
for (i = 0; i < num_grid_points * num_band0; i++) {
gamma_ij[i] = 0;
}
#ifdef PHPYOPENMP
#pragma omp parallel for private(j, k, l, m, f, gp, e1_r, e1_i, a, b, dist, sum_g_k)
#pragma omp parallel for private(j, k, l, m, f, gp, e1_r, e1_i, a, b, dist, \
sum_g_k)
#endif
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;
}
sum_g_k = 0;
for (k = 0; k < num_band; k++)
{ /* band index */
f = frequencies[gp * num_band + k];
if (f < cutoff_frequency)
{
continue;
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;
}
sum_g_k = 0;
for (k = 0; k < num_band; k++) { /* band index */
f = frequencies[gp * num_band + k];
if (f < cutoff_frequency) {
continue;
}
dist = integration_weights[gp * num_band0 * num_band +
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;
}
}
gamma_ij[gp * num_band0 + j] = sum_g_k * weights[gp];
}
dist = integration_weights[gp * num_band0 * num_band +
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;
}
for (i = 0; i < num_band0; i++) {
gamma[i] = 0;
}
for (i = 0; i < num_grid_points; i++) {
gp = ir_grid_points[i];
for (j = 0; j < num_band0; j++) {
gamma[j] += gamma_ij[gp * num_band0 + j];
}
}
gamma_ij[gp * num_band0 + j] = sum_g_k * weights[gp];
}
}
for (i = 0; i < num_band0; i++)
{
gamma[i] = 0;
}
for (i = 0; i < num_grid_points; i++)
{
gp = ir_grid_points[i];
for (j = 0; j < num_band0; j++)
{
gamma[j] += gamma_ij[gp * num_band0 + j];
for (i = 0; i < num_band0; i++) {
/* Frequency unit to ang-freq: *(2pi)**2/(2pi) */
/* Ang-freq to freq unit (for lifetime): /2pi */
/* gamma = 1/2t */
gamma[i] *= M_2PI / 4 * f0[i] * f0[i] / 2;
}
}
for (i = 0; i < num_band0; i++)
{
/* Frequency unit to ang-freq: *(2pi)**2/(2pi) */
/* Ang-freq to freq unit (for lifetime): /2pi */
/* gamma = 1/2t */
gamma[i] *= M_2PI / 4 * f0[i] * f0[i] / 2;
}
free(gamma_ij);
gamma_ij = NULL;
free(f0);
f0 = NULL;
free(e0_r);
e0_r = NULL;
free(e0_i);
e0_i = NULL;
free(gamma_ij);
gamma_ij = NULL;
free(f0);
f0 = NULL;
free(e0_r);
e0_r = NULL;
free(e0_i);
e0_i = NULL;
}

View File

@ -37,28 +37,16 @@
#include "lapack_wrapper.h"
void iso_get_isotope_scattering_strength(double *gamma,
const long grid_point,
const double *mass_variances,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long num_grid_points,
const long *band_indices,
const long num_band,
const long num_band0,
const double sigma,
const double cutoff_frequency);
void iso_get_thm_isotope_scattering_strength(double *gamma,
const long grid_point,
const long *ir_grid_points,
const long *weights,
const double *mass_variances,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long num_grid_points,
const long *band_indices,
const long num_band,
const long num_band0,
const double *integration_weights,
const double cutoff_frequency);
void iso_get_isotope_scattering_strength(
double *gamma, const long grid_point, const double *mass_variances,
const double *frequencies, const lapack_complex_double *eigenvectors,
const long num_grid_points, const long *band_indices, const long num_band,
const long num_band0, const double sigma, const double cutoff_frequency);
void iso_get_thm_isotope_scattering_strength(
double *gamma, const long grid_point, const long *ir_grid_points,
const long *weights, const double *mass_variances,
const double *frequencies, const lapack_complex_double *eigenvectors,
const long num_grid_points, const long *band_indices, const long num_band,
const long num_band0, const double *integration_weights,
const double cutoff_frequency);
#endif

View File

@ -34,265 +34,216 @@
#include "lagrid.h"
long lagmat_get_determinant_l3(const long a[3][3])
{
return a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1]) + a[0][1] * (a[1][2] * a[2][0] - a[1][0] * a[2][2]) + a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);
long lagmat_get_determinant_l3(const long a[3][3]) {
return a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1]) +
a[0][1] * (a[1][2] * a[2][0] - a[1][0] * a[2][2]) +
a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);
}
double lagmat_get_determinant_d3(const double a[3][3])
{
return a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1]) + a[0][1] * (a[1][2] * a[2][0] - a[1][0] * a[2][2]) + a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);
double lagmat_get_determinant_d3(const double a[3][3]) {
return a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1]) +
a[0][1] * (a[1][2] * a[2][0] - a[1][0] * a[2][2]) +
a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);
}
void lagmat_cast_matrix_3l_to_3d(double m[3][3], const long a[3][3])
{
m[0][0] = a[0][0];
m[0][1] = a[0][1];
m[0][2] = a[0][2];
m[1][0] = a[1][0];
m[1][1] = a[1][1];
m[1][2] = a[1][2];
m[2][0] = a[2][0];
m[2][1] = a[2][1];
m[2][2] = a[2][2];
void lagmat_cast_matrix_3l_to_3d(double m[3][3], const long a[3][3]) {
m[0][0] = a[0][0];
m[0][1] = a[0][1];
m[0][2] = a[0][2];
m[1][0] = a[1][0];
m[1][1] = a[1][1];
m[1][2] = a[1][2];
m[2][0] = a[2][0];
m[2][1] = a[2][1];
m[2][2] = a[2][2];
}
void lagmat_cast_matrix_3d_to_3l(long m[3][3], const double a[3][3])
{
m[0][0] = lagmat_Nint(a[0][0]);
m[0][1] = lagmat_Nint(a[0][1]);
m[0][2] = lagmat_Nint(a[0][2]);
m[1][0] = lagmat_Nint(a[1][0]);
m[1][1] = lagmat_Nint(a[1][1]);
m[1][2] = lagmat_Nint(a[1][2]);
m[2][0] = lagmat_Nint(a[2][0]);
m[2][1] = lagmat_Nint(a[2][1]);
m[2][2] = lagmat_Nint(a[2][2]);
void lagmat_cast_matrix_3d_to_3l(long m[3][3], const double a[3][3]) {
m[0][0] = lagmat_Nint(a[0][0]);
m[0][1] = lagmat_Nint(a[0][1]);
m[0][2] = lagmat_Nint(a[0][2]);
m[1][0] = lagmat_Nint(a[1][0]);
m[1][1] = lagmat_Nint(a[1][1]);
m[1][2] = lagmat_Nint(a[1][2]);
m[2][0] = lagmat_Nint(a[2][0]);
m[2][1] = lagmat_Nint(a[2][1]);
m[2][2] = lagmat_Nint(a[2][2]);
}
long lagmat_get_similar_matrix_ld3(double m[3][3],
const long a[3][3],
long lagmat_get_similar_matrix_ld3(double m[3][3], const long a[3][3],
const double b[3][3],
const double precision)
{
double c[3][3];
if (!lagmat_inverse_matrix_d3(c, b, precision))
{
warning_print("No similar matrix due to 0 determinant.\n");
return 0;
}
lagmat_multiply_matrix_ld3(m, a, b);
lagmat_multiply_matrix_d3(m, c, m);
return 1;
}
long lagmat_check_identity_matrix_l3(const long a[3][3],
const long b[3][3])
{
if (a[0][0] - b[0][0] ||
a[0][1] - b[0][1] ||
a[0][2] - b[0][2] ||
a[1][0] - b[1][0] ||
a[1][1] - b[1][1] ||
a[1][2] - b[1][2] ||
a[2][0] - b[2][0] ||
a[2][1] - b[2][1] ||
a[2][2] - b[2][2])
{
return 0;
}
else
{
const double precision) {
double c[3][3];
if (!lagmat_inverse_matrix_d3(c, b, precision)) {
warning_print("No similar matrix due to 0 determinant.\n");
return 0;
}
lagmat_multiply_matrix_ld3(m, a, b);
lagmat_multiply_matrix_d3(m, c, m);
return 1;
}
}
long lagmat_check_identity_matrix_ld3(const long a[3][3],
const double b[3][3],
const double symprec)
{
if (lagmat_Dabs(a[0][0] - b[0][0]) > symprec ||
lagmat_Dabs(a[0][1] - b[0][1]) > symprec ||
lagmat_Dabs(a[0][2] - b[0][2]) > symprec ||
lagmat_Dabs(a[1][0] - b[1][0]) > symprec ||
lagmat_Dabs(a[1][1] - b[1][1]) > symprec ||
lagmat_Dabs(a[1][2] - b[1][2]) > symprec ||
lagmat_Dabs(a[2][0] - b[2][0]) > symprec ||
lagmat_Dabs(a[2][1] - b[2][1]) > symprec ||
lagmat_Dabs(a[2][2] - b[2][2]) > symprec)
{
return 0;
}
else
{
long lagmat_check_identity_matrix_l3(const long a[3][3], const long b[3][3]) {
if (a[0][0] - b[0][0] || a[0][1] - b[0][1] || a[0][2] - b[0][2] ||
a[1][0] - b[1][0] || a[1][1] - b[1][1] || a[1][2] - b[1][2] ||
a[2][0] - b[2][0] || a[2][1] - b[2][1] || a[2][2] - b[2][2]) {
return 0;
} else {
return 1;
}
}
long lagmat_check_identity_matrix_ld3(const long a[3][3], const double b[3][3],
const double symprec) {
if (lagmat_Dabs(a[0][0] - b[0][0]) > symprec ||
lagmat_Dabs(a[0][1] - b[0][1]) > symprec ||
lagmat_Dabs(a[0][2] - b[0][2]) > symprec ||
lagmat_Dabs(a[1][0] - b[1][0]) > symprec ||
lagmat_Dabs(a[1][1] - b[1][1]) > symprec ||
lagmat_Dabs(a[1][2] - b[1][2]) > symprec ||
lagmat_Dabs(a[2][0] - b[2][0]) > symprec ||
lagmat_Dabs(a[2][1] - b[2][1]) > symprec ||
lagmat_Dabs(a[2][2] - b[2][2]) > symprec) {
return 0;
} else {
return 1;
}
}
long lagmat_inverse_matrix_d3(double m[3][3], const double a[3][3],
const double precision) {
double det;
double c[3][3];
det = lagmat_get_determinant_d3(a);
if (lagmat_Dabs(det) < precision) {
warning_print("No inverse matrix (det=%f)\n", det);
return 0;
}
c[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det;
c[1][0] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) / det;
c[2][0] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det;
c[0][1] = (a[2][1] * a[0][2] - a[2][2] * a[0][1]) / det;
c[1][1] = (a[2][2] * a[0][0] - a[2][0] * a[0][2]) / det;
c[2][1] = (a[2][0] * a[0][1] - a[2][1] * a[0][0]) / det;
c[0][2] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det;
c[1][2] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) / det;
c[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det;
lagmat_copy_matrix_d3(m, c);
return 1;
}
}
long lagmat_inverse_matrix_d3(double m[3][3],
const double a[3][3],
const double precision)
{
double det;
double c[3][3];
det = lagmat_get_determinant_d3(a);
if (lagmat_Dabs(det) < precision)
{
warning_print("No inverse matrix (det=%f)\n", det);
return 0;
}
c[0][0] = (a[1][1] * a[2][2] - a[1][2] * a[2][1]) / det;
c[1][0] = (a[1][2] * a[2][0] - a[1][0] * a[2][2]) / det;
c[2][0] = (a[1][0] * a[2][1] - a[1][1] * a[2][0]) / det;
c[0][1] = (a[2][1] * a[0][2] - a[2][2] * a[0][1]) / det;
c[1][1] = (a[2][2] * a[0][0] - a[2][0] * a[0][2]) / det;
c[2][1] = (a[2][0] * a[0][1] - a[2][1] * a[0][0]) / det;
c[0][2] = (a[0][1] * a[1][2] - a[0][2] * a[1][1]) / det;
c[1][2] = (a[0][2] * a[1][0] - a[0][0] * a[1][2]) / det;
c[2][2] = (a[0][0] * a[1][1] - a[0][1] * a[1][0]) / det;
lagmat_copy_matrix_d3(m, c);
return 1;
void lagmat_transpose_matrix_l3(long a[3][3], const long b[3][3]) {
long c[3][3];
c[0][0] = b[0][0];
c[0][1] = b[1][0];
c[0][2] = b[2][0];
c[1][0] = b[0][1];
c[1][1] = b[1][1];
c[1][2] = b[2][1];
c[2][0] = b[0][2];
c[2][1] = b[1][2];
c[2][2] = b[2][2];
lagmat_copy_matrix_l3(a, c);
}
void lagmat_transpose_matrix_l3(long a[3][3], const long b[3][3])
{
long c[3][3];
c[0][0] = b[0][0];
c[0][1] = b[1][0];
c[0][2] = b[2][0];
c[1][0] = b[0][1];
c[1][1] = b[1][1];
c[1][2] = b[2][1];
c[2][0] = b[0][2];
c[2][1] = b[1][2];
c[2][2] = b[2][2];
lagmat_copy_matrix_l3(a, c);
}
void lagmat_multiply_matrix_vector_l3(long v[3],
const long a[3][3],
const long b[3])
{
long i;
long c[3];
for (i = 0; i < 3; i++)
{
c[i] = a[i][0] * b[0] + a[i][1] * b[1] + a[i][2] * b[2];
}
for (i = 0; i < 3; i++)
{
v[i] = c[i];
}
}
void lagmat_multiply_matrix_l3(long m[3][3],
const long a[3][3],
const long b[3][3])
{
long i, j; /* a_ij */
long c[3][3];
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
c[i][j] =
a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j];
void lagmat_multiply_matrix_vector_l3(long v[3], const long a[3][3],
const long b[3]) {
long i;
long c[3];
for (i = 0; i < 3; i++) {
c[i] = a[i][0] * b[0] + a[i][1] * b[1] + a[i][2] * b[2];
}
}
lagmat_copy_matrix_l3(m, c);
}
void lagmat_multiply_matrix_ld3(double m[3][3],
const long a[3][3],
const double b[3][3])
{
long i, j; /* a_ij */
double c[3][3];
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
c[i][j] =
a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j];
for (i = 0; i < 3; i++) {
v[i] = c[i];
}
}
lagmat_copy_matrix_d3(m, c);
}
void lagmat_multiply_matrix_d3(double m[3][3],
const double a[3][3],
const double b[3][3])
{
long i, j; /* a_ij */
double c[3][3];
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
c[i][j] =
a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j];
void lagmat_multiply_matrix_l3(long m[3][3], const long a[3][3],
const long b[3][3]) {
long i, j; /* a_ij */
long c[3][3];
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j];
}
}
}
lagmat_copy_matrix_d3(m, c);
lagmat_copy_matrix_l3(m, c);
}
void lagmat_copy_matrix_l3(long a[3][3], const long b[3][3])
{
a[0][0] = b[0][0];
a[0][1] = b[0][1];
a[0][2] = b[0][2];
a[1][0] = b[1][0];
a[1][1] = b[1][1];
a[1][2] = b[1][2];
a[2][0] = b[2][0];
a[2][1] = b[2][1];
a[2][2] = b[2][2];
void lagmat_multiply_matrix_ld3(double m[3][3], const long a[3][3],
const double b[3][3]) {
long i, j; /* a_ij */
double c[3][3];
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j];
}
}
lagmat_copy_matrix_d3(m, c);
}
void lagmat_copy_matrix_d3(double a[3][3], const double b[3][3])
{
a[0][0] = b[0][0];
a[0][1] = b[0][1];
a[0][2] = b[0][2];
a[1][0] = b[1][0];
a[1][1] = b[1][1];
a[1][2] = b[1][2];
a[2][0] = b[2][0];
a[2][1] = b[2][1];
a[2][2] = b[2][2];
void lagmat_multiply_matrix_d3(double m[3][3], const double a[3][3],
const double b[3][3]) {
long i, j; /* a_ij */
double c[3][3];
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j];
}
}
lagmat_copy_matrix_d3(m, c);
}
void lagmat_copy_vector_l3(long a[3], const long b[3])
{
a[0] = b[0];
a[1] = b[1];
a[2] = b[2];
void lagmat_copy_matrix_l3(long a[3][3], const long b[3][3]) {
a[0][0] = b[0][0];
a[0][1] = b[0][1];
a[0][2] = b[0][2];
a[1][0] = b[1][0];
a[1][1] = b[1][1];
a[1][2] = b[1][2];
a[2][0] = b[2][0];
a[2][1] = b[2][1];
a[2][2] = b[2][2];
}
long lagmat_modulo_l(const long a, const long b)
{
long c;
c = a % b;
if (c < 0)
{
c += b;
}
return c;
void lagmat_copy_matrix_d3(double a[3][3], const double b[3][3]) {
a[0][0] = b[0][0];
a[0][1] = b[0][1];
a[0][2] = b[0][2];
a[1][0] = b[1][0];
a[1][1] = b[1][1];
a[1][2] = b[1][2];
a[2][0] = b[2][0];
a[2][1] = b[2][1];
a[2][2] = b[2][2];
}
long lagmat_Nint(const double a)
{
if (a < 0.0)
return (long)(a - 0.5);
else
return (long)(a + 0.5);
void lagmat_copy_vector_l3(long a[3], const long b[3]) {
a[0] = b[0];
a[1] = b[1];
a[2] = b[2];
}
double lagmat_Dabs(const double a)
{
if (a < 0.0)
return -a;
else
return a;
long lagmat_modulo_l(const long a, const long b) {
long c;
c = a % b;
if (c < 0) {
c += b;
}
return c;
}
long lagmat_Nint(const double a) {
if (a < 0.0)
return (long)(a - 0.5);
else
return (long)(a + 0.5);
}
double lagmat_Dabs(const double a) {
if (a < 0.0)
return -a;
else
return a;
}

View File

@ -36,7 +36,7 @@
#define __lagrid_H__
#ifdef LAGWARNING
#define warning_print(...) fprintf(stderr,__VA_ARGS__)
#define warning_print(...) fprintf(stderr, __VA_ARGS__)
#else
#define warning_print(...)
#endif
@ -45,30 +45,22 @@ long lagmat_get_determinant_l3(const long a[3][3]);
double lagmat_get_determinant_d3(const double a[3][3]);
void lagmat_cast_matrix_3l_to_3d(double m[3][3], const long a[3][3]);
void lagmat_cast_matrix_3d_to_3l(long m[3][3], const double a[3][3]);
long lagmat_get_similar_matrix_ld3(double m[3][3],
const long a[3][3],
long lagmat_get_similar_matrix_ld3(double m[3][3], const long a[3][3],
const double b[3][3],
const double precision);
long lagmat_check_identity_matrix_l3(const long a[3][3],
const long b[3][3]);
long lagmat_check_identity_matrix_ld3(const long a[3][3],
const double b[3][3],
long lagmat_check_identity_matrix_l3(const long a[3][3], const long b[3][3]);
long lagmat_check_identity_matrix_ld3(const long a[3][3], const double b[3][3],
const double symprec);
long lagmat_inverse_matrix_d3(double m[3][3],
const double a[3][3],
long lagmat_inverse_matrix_d3(double m[3][3], const double a[3][3],
const double precision);
void lagmat_transpose_matrix_l3(long a[3][3], const long b[3][3]);
void lagmat_multiply_matrix_vector_l3(long v[3],
const long a[3][3],
void lagmat_multiply_matrix_vector_l3(long v[3], const long a[3][3],
const long b[3]);
void lagmat_multiply_matrix_l3(long m[3][3],
const long a[3][3],
void lagmat_multiply_matrix_l3(long m[3][3], const long a[3][3],
const long b[3][3]);
void lagmat_multiply_matrix_ld3(double m[3][3],
const long a[3][3],
void lagmat_multiply_matrix_ld3(double m[3][3], const long a[3][3],
const double b[3][3]);
void lagmat_multiply_matrix_d3(double m[3][3],
const double a[3][3],
void lagmat_multiply_matrix_d3(double m[3][3], const double a[3][3],
const double b[3][3]);
void lagmat_copy_matrix_l3(long a[3][3], const long b[3][3]);
void lagmat_copy_matrix_d3(double a[3][3], const double b[3][3]);

View File

@ -37,12 +37,11 @@
#define min(a, b) ((a) > (b) ? (b) : (a))
#ifdef MKL_LAPACKE
MKL_Complex16 lapack_make_complex_double(double re, double im)
{
MKL_Complex16 z;
z.real = re;
z.imag = im;
return z;
MKL_Complex16 lapack_make_complex_double(double re, double im) {
MKL_Complex16 z;
z.real = re;
z.imag = im;
return z;
}
#ifndef LAPACKE_malloc
#define LAPACKE_malloc(size) malloc(size)
@ -52,204 +51,146 @@ MKL_Complex16 lapack_make_complex_double(double re, double im)
#endif
#endif
int phonopy_zheev(double *w,
lapack_complex_double *a,
const int n,
const char uplo)
{
lapack_int info;
info = LAPACKE_zheev(LAPACK_ROW_MAJOR, 'V', uplo,
(lapack_int)n, a, (lapack_int)n, w);
return (int)info;
int phonopy_zheev(double *w, lapack_complex_double *a, const int n,
const char uplo) {
lapack_int info;
info = LAPACKE_zheev(LAPACK_ROW_MAJOR, 'V', uplo, (lapack_int)n, a,
(lapack_int)n, w);
return (int)info;
}
int phonopy_pinv(double *data_out,
const double *data_in,
const int m,
const int n,
const double cutoff)
{
int i, j, k;
lapack_int info;
double *s, *a, *u, *vt, *superb;
int phonopy_pinv(double *data_out, const double *data_in, const int m,
const int n, const double cutoff) {
int i, j, k;
lapack_int info;
double *s, *a, *u, *vt, *superb;
a = (double *)malloc(sizeof(double) * m * n);
s = (double *)malloc(sizeof(double) * min(m, n));
u = (double *)malloc(sizeof(double) * m * m);
vt = (double *)malloc(sizeof(double) * n * n);
superb = (double *)malloc(sizeof(double) * (min(m, n) - 1));
a = (double *)malloc(sizeof(double) * m * n);
s = (double *)malloc(sizeof(double) * min(m, n));
u = (double *)malloc(sizeof(double) * m * m);
vt = (double *)malloc(sizeof(double) * n * n);
superb = (double *)malloc(sizeof(double) * (min(m, n) - 1));
for (i = 0; i < m * n; i++)
{
a[i] = data_in[i];
}
info = LAPACKE_dgesvd(LAPACK_ROW_MAJOR,
'A',
'A',
(lapack_int)m,
(lapack_int)n,
a,
(lapack_int)n,
s,
u,
(lapack_int)m,
vt,
(lapack_int)n,
superb);
for (i = 0; i < n * m; i++)
{
data_out[i] = 0;
}
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
for (k = 0; k < min(m, n); k++)
{
if (s[k] > cutoff)
{
data_out[j * m + i] += u[i * m + k] / s[k] * vt[k * n + j];
}
}
for (i = 0; i < m * n; i++) {
a[i] = data_in[i];
}
}
free(a);
free(s);
free(u);
free(vt);
free(superb);
info = LAPACKE_dgesvd(LAPACK_ROW_MAJOR, 'A', 'A', (lapack_int)m,
(lapack_int)n, a, (lapack_int)n, s, u, (lapack_int)m,
vt, (lapack_int)n, superb);
return (int)info;
for (i = 0; i < n * m; i++) {
data_out[i] = 0;
}
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
for (k = 0; k < min(m, n); k++) {
if (s[k] > cutoff) {
data_out[j * m + i] += u[i * m + k] / s[k] * vt[k * n + j];
}
}
}
}
free(a);
free(s);
free(u);
free(vt);
free(superb);
return (int)info;
}
void phonopy_pinv_mt(double *data_out,
int *info_out,
const double *data_in,
const int num_thread,
const int *row_nums,
const int max_row_num,
const int column_num,
const double cutoff)
{
int i;
void phonopy_pinv_mt(double *data_out, int *info_out, const double *data_in,
const int num_thread, const int *row_nums,
const int max_row_num, const int column_num,
const double cutoff) {
int i;
#ifdef PHPYOPENMP
#pragma omp parallel for
#endif
for (i = 0; i < num_thread; i++)
{
info_out[i] = phonopy_pinv(data_out + i * max_row_num * column_num,
data_in + i * max_row_num * column_num,
row_nums[i],
column_num,
cutoff);
}
for (i = 0; i < num_thread; i++) {
info_out[i] = phonopy_pinv(data_out + i * max_row_num * column_num,
data_in + i * max_row_num * column_num,
row_nums[i], column_num, cutoff);
}
}
int phonopy_dsyev(double *data,
double *eigvals,
const int size,
const int algorithm)
{
lapack_int info;
int phonopy_dsyev(double *data, double *eigvals, const int size,
const int algorithm) {
lapack_int info;
lapack_int liwork;
long lwork;
lapack_int *iwork;
double *work;
lapack_int iwork_query;
double work_query;
lapack_int liwork;
long lwork;
lapack_int *iwork;
double *work;
lapack_int iwork_query;
double work_query;
info = 0;
liwork = -1;
lwork = -1;
iwork = NULL;
work = NULL;
info = 0;
liwork = -1;
lwork = -1;
iwork = NULL;
work = NULL;
switch (algorithm)
{
case 0: /* dsyev */
info = LAPACKE_dsyev(LAPACK_COL_MAJOR,
'V',
'U',
(lapack_int)size,
data,
(lapack_int)size,
eigvals);
break;
case 1: /* dsyevd */
info = LAPACKE_dsyevd_work(LAPACK_COL_MAJOR,
'V',
'U',
(lapack_int)size,
data,
(lapack_int)size,
eigvals,
&work_query,
lwork,
&iwork_query,
liwork);
liwork = iwork_query;
lwork = (long)work_query;
/* printf("liwork %d, lwork %ld\n", liwork, lwork); */
if ((iwork = (lapack_int *)LAPACKE_malloc(sizeof(lapack_int) * liwork)) == NULL)
{
goto end;
};
if ((work = (double *)LAPACKE_malloc(sizeof(double) * lwork)) == NULL)
{
goto end;
switch (algorithm) {
case 0: /* dsyev */
info = LAPACKE_dsyev(LAPACK_COL_MAJOR, 'V', 'U', (lapack_int)size,
data, (lapack_int)size, eigvals);
break;
case 1: /* dsyevd */
info = LAPACKE_dsyevd_work(LAPACK_COL_MAJOR, 'V', 'U',
(lapack_int)size, data, (lapack_int)size,
eigvals, &work_query, lwork,
&iwork_query, liwork);
liwork = iwork_query;
lwork = (long)work_query;
/* printf("liwork %d, lwork %ld\n", liwork, lwork); */
if ((iwork = (lapack_int *)LAPACKE_malloc(sizeof(lapack_int) *
liwork)) == NULL) {
goto end;
};
if ((work = (double *)LAPACKE_malloc(sizeof(double) * lwork)) ==
NULL) {
goto end;
}
info = LAPACKE_dsyevd_work(LAPACK_COL_MAJOR, 'V', 'U',
(lapack_int)size, data, (lapack_int)size,
eigvals, work, lwork, iwork, liwork);
end:
if (iwork) {
LAPACKE_free(iwork);
iwork = NULL;
}
if (work) {
LAPACKE_free(work);
work = NULL;
}
/* info = LAPACKE_dsyevd(LAPACK_COL_MAJOR, */
/* 'V', */
/* 'U', */
/* (lapack_int)size, */
/* data, */
/* (lapack_int)size, */
/* eigvals); */
break;
}
info = LAPACKE_dsyevd_work(LAPACK_COL_MAJOR,
'V',
'U',
(lapack_int)size,
data,
(lapack_int)size,
eigvals,
work,
lwork,
iwork,
liwork);
end:
if (iwork)
{
LAPACKE_free(iwork);
iwork = NULL;
}
if (work)
{
LAPACKE_free(work);
work = NULL;
}
/* info = LAPACKE_dsyevd(LAPACK_COL_MAJOR, */
/* 'V', */
/* 'U', */
/* (lapack_int)size, */
/* data, */
/* (lapack_int)size, */
/* eigvals); */
break;
}
return (int)info;
return (int)info;
}
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;
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;
}

View File

@ -45,30 +45,18 @@ MKL_Complex16 lapack_make_complex_double(double re, double im);
#include <lapacke.h>
#endif
int phonopy_zheev(double *w,
lapack_complex_double *a,
const int n,
int phonopy_zheev(double *w, lapack_complex_double *a, const int n,
const char uplo);
int phonopy_pinv(double *data_out,
const double *data_in,
const int m,
const int n,
const double cutoff);
void phonopy_pinv_mt(double *data_out,
int *info_out,
const double *data_in,
const int num_thread,
const int *row_nums,
const int max_row_num,
const int column_num,
int phonopy_pinv(double *data_out, const double *data_in, const int m,
const int n, const double cutoff);
void phonopy_pinv_mt(double *data_out, int *info_out, const double *data_in,
const int num_thread, const int *row_nums,
const int max_row_num, const int column_num,
const double cutoff);
int phonopy_dsyev(double *data,
double *eigvals,
const int size,
int phonopy_dsyev(double *data, double *eigvals, const int size,
const int algorithm);
lapack_complex_double
phonoc_complex_prod(const lapack_complex_double a,
const lapack_complex_double b);
lapack_complex_double phonoc_complex_prod(const lapack_complex_double a,
const lapack_complex_double b);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -42,251 +42,130 @@
#endif
#include "phonoc_array.h"
long ph3py_get_interaction(Darray *fc3_normal_squared,
const char *g_zero,
const Darray *frequencies,
const lapack_complex_double *eigenvectors,
const long (*triplets)[3],
const long num_triplets,
const long (*bz_grid_addresses)[3],
const long D_diag[3],
const long Q[3][3],
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multi)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const long *band_indices,
const long symmetrize_fc3_q,
const double cutoff_frequency);
long ph3py_get_pp_collision(double *imag_self_energy,
const long relative_grid_address[24][4][3], /* thm */
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long (*triplets)[3],
const long num_triplets,
const long *triplet_weights,
const long (*bz_grid_addresses)[3], /* thm */
const long *bz_map, /* thm */
const long bz_grid_type,
const long D_diag[3],
const long Q[3][3],
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multi)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const Larray *band_indices,
const Darray *temperatures,
const long is_NU,
const long symmetrize_fc3_q,
const double cutoff_frequency);
long ph3py_get_pp_collision_with_sigma(
long ph3py_get_interaction(
Darray *fc3_normal_squared, const char *g_zero, const Darray *frequencies,
const lapack_complex_double *eigenvectors, const long (*triplets)[3],
const long num_triplets, const long (*bz_grid_addresses)[3],
const long D_diag[3], const long Q[3][3], const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multi)[2], const double *masses,
const long *p2s_map, const long *s2p_map, const long *band_indices,
const long symmetrize_fc3_q, const double cutoff_frequency);
long ph3py_get_pp_collision(
double *imag_self_energy,
const double sigma,
const double sigma_cutoff,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long (*triplets)[3],
const long num_triplets,
const long *triplet_weights,
const long (*bz_grid_addresses)[3],
const long D_diag[3],
const long Q[3][3],
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multi)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const Larray *band_indices,
const Darray *temperatures,
const long is_NU,
const long symmetrize_fc3_q,
const long relative_grid_address[24][4][3], /* thm */
const double *frequencies, const lapack_complex_double *eigenvectors,
const long (*triplets)[3], const long num_triplets,
const long *triplet_weights, const long (*bz_grid_addresses)[3], /* thm */
const long *bz_map, /* thm */
const long bz_grid_type, const long D_diag[3], const long Q[3][3],
const double *fc3, const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multi)[2], const double *masses,
const long *p2s_map, const long *s2p_map, const Larray *band_indices,
const Darray *temperatures, const long is_NU, const long symmetrize_fc3_q,
const double cutoff_frequency);
long ph3py_get_pp_collision_with_sigma(
double *imag_self_energy, const double sigma, const double sigma_cutoff,
const double *frequencies, const lapack_complex_double *eigenvectors,
const long (*triplets)[3], const long num_triplets,
const long *triplet_weights, const long (*bz_grid_addresses)[3],
const long D_diag[3], const long Q[3][3], const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multi)[2], const double *masses,
const long *p2s_map, const long *s2p_map, const Larray *band_indices,
const Darray *temperatures, const long is_NU, const long symmetrize_fc3_q,
const double cutoff_frequency);
void ph3py_get_imag_self_energy_at_bands_with_g(
double *imag_self_energy,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const double *g,
const char *g_zero,
const double temperature,
const double cutoff_frequency,
const long num_frequency_points,
const long frequency_point_index);
double *imag_self_energy, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplet_weights, const double *g, const char *g_zero,
const double temperature, const double cutoff_frequency,
const long num_frequency_points, const long frequency_point_index);
void ph3py_get_detailed_imag_self_energy_at_bands_with_g(
double *detailed_imag_self_energy,
double *imag_self_energy_N,
double *imag_self_energy_U,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const long (*bz_grid_addresses)[3],
const double *g,
const char *g_zero,
const double temperature,
double *detailed_imag_self_energy, double *imag_self_energy_N,
double *imag_self_energy_U, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplet_weights, const long (*bz_grid_addresses)[3],
const double *g, const char *g_zero, const double temperature,
const double cutoff_frequency);
void ph3py_get_real_self_energy_at_bands(double *real_self_energy,
const Darray *fc3_normal_squared,
const long *band_indices,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const double epsilon,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency);
void ph3py_get_real_self_energy_at_bands(
double *real_self_energy, const Darray *fc3_normal_squared,
const long *band_indices, const double *frequencies,
const long (*triplets)[3], const long *triplet_weights,
const double epsilon, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency);
void ph3py_get_real_self_energy_at_frequency_point(
double *real_self_energy,
const double frequency_point,
const Darray *fc3_normal_squared,
const long *band_indices,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const double epsilon,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency);
void ph3py_get_collision_matrix(double *collision_matrix,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplets_map,
const long *map_q,
const long *rotated_grid_points,
const double *rotations_cartesian,
const double *g,
const long num_ir_gp,
const long num_gp,
const long num_rot,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency);
void ph3py_get_reducible_collision_matrix(double *collision_matrix,
const Darray *fc3_normal_squared,
const double *frequencies,
const long (*triplets)[3],
const long *triplets_map,
const long *map_q,
const double *g,
const long num_gp,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency);
double *real_self_energy, const double frequency_point,
const Darray *fc3_normal_squared, const long *band_indices,
const double *frequencies, const long (*triplets)[3],
const long *triplet_weights, const double epsilon, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency);
void ph3py_get_collision_matrix(
double *collision_matrix, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplets_map, const long *map_q,
const long *rotated_grid_points, const double *rotations_cartesian,
const double *g, const long num_ir_gp, const long num_gp,
const long num_rot, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency);
void ph3py_get_reducible_collision_matrix(
double *collision_matrix, const Darray *fc3_normal_squared,
const double *frequencies, const long (*triplets)[3],
const long *triplets_map, const long *map_q, const double *g,
const long num_gp, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency);
void ph3py_get_isotope_scattering_strength(
double *gamma,
const long grid_point,
const double *mass_variances,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long num_grid_points,
const long *band_indices,
const long num_band,
const long num_band0,
const double sigma,
const double cutoff_frequency);
double *gamma, const long grid_point, const double *mass_variances,
const double *frequencies, const lapack_complex_double *eigenvectors,
const long num_grid_points, const long *band_indices, const long num_band,
const long num_band0, const double sigma, const double cutoff_frequency);
void ph3py_get_thm_isotope_scattering_strength(
double *gamma,
const long grid_point,
const long *ir_grid_points,
const long *weights,
const double *mass_variances,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long num_ir_grid_points,
const long *band_indices,
const long num_band,
const long num_band0,
const double *integration_weights,
const double cutoff_frequency);
void ph3py_distribute_fc3(double *fc3,
const long target,
const long source,
const long *atom_mapping,
const long num_atom,
double *gamma, const long grid_point, const long *ir_grid_points,
const long *weights, const double *mass_variances,
const double *frequencies, const lapack_complex_double *eigenvectors,
const long num_ir_grid_points, const long *band_indices,
const long num_band, const long num_band0,
const double *integration_weights, const double cutoff_frequency);
void ph3py_distribute_fc3(double *fc3, const long target, const long source,
const long *atom_mapping, const long num_atom,
const double *rot_cart);
void ph3py_rotate_delta_fc2(double (*fc3)[3][3][3],
const double (*delta_fc2s)[3][3],
const double *inv_U,
const double (*site_sym_cart)[3][3],
const long *rot_map_syms,
const long num_atom,
const long num_site_sym,
const long num_disp);
const long *rot_map_syms, const long num_atom,
const long num_site_sym, const long num_disp);
void ph3py_get_permutation_symmetry_fc3(double *fc3, const long num_atom);
void ph3py_get_permutation_symmetry_compact_fc3(double *fc3,
const long p2s[],
const long s2pp[],
const long nsym_list[],
const long perms[],
const long n_satom,
const long n_patom);
void ph3py_transpose_compact_fc3(double *fc3,
const long p2s[],
const long s2pp[],
const long nsym_list[],
const long perms[],
const long n_satom,
const long n_patom,
const long t_type);
long ph3py_get_triplets_reciprocal_mesh_at_q(long *map_triplets,
long *map_q,
const long grid_point,
const long mesh[3],
const long is_time_reversal,
const long num_rot,
const long (*rec_rotations)[3][3],
const long swappable);
long ph3py_get_BZ_triplets_at_q(long (*triplets)[3],
const long grid_point,
void ph3py_get_permutation_symmetry_compact_fc3(
double *fc3, const long p2s[], const long s2pp[], const long nsym_list[],
const long perms[], const long n_satom, const long n_patom);
void ph3py_transpose_compact_fc3(double *fc3, const long p2s[],
const long s2pp[], const long nsym_list[],
const long perms[], const long n_satom,
const long n_patom, const long t_type);
long ph3py_get_triplets_reciprocal_mesh_at_q(
long *map_triplets, long *map_q, const long grid_point, const long mesh[3],
const long is_time_reversal, const long num_rot,
const long (*rec_rotations)[3][3], const long swappable);
long ph3py_get_BZ_triplets_at_q(long (*triplets)[3], const long grid_point,
const long (*bz_grid_addresses)[3],
const long *bz_map,
const long *map_triplets,
const long *bz_map, const long *map_triplets,
const long num_map_triplets,
const long D_diag[3],
const long Q[3][3],
const long D_diag[3], const long Q[3][3],
const long bz_grid_type);
long ph3py_get_integration_weight(double *iw,
char *iw_zero,
const double *frequency_points,
const long num_band0,
const long relative_grid_address[24][4][3],
const long mesh[3],
const long (*triplets)[3],
const long num_triplets,
const long (*bz_grid_addresses)[3],
const long *bz_map,
const long bz_grid_type,
const double *frequencies1,
const long num_band1,
const double *frequencies2,
const long num_band2,
const long tp_type,
const long openmp_per_triplets,
const long openmp_per_bands);
void ph3py_get_integration_weight_with_sigma(double *iw,
char *iw_zero,
const double sigma,
const double sigma_cutoff,
const double *frequency_points,
const long num_band0,
const long (*triplets)[3],
const long num_triplets,
const double *frequencies,
const long num_band,
const long tp_type);
long ph3py_get_integration_weight(
double *iw, char *iw_zero, const double *frequency_points,
const long num_band0, const long relative_grid_address[24][4][3],
const long mesh[3], const long (*triplets)[3], const long num_triplets,
const long (*bz_grid_addresses)[3], const long *bz_map,
const long bz_grid_type, const double *frequencies1, const long num_band1,
const double *frequencies2, const long num_band2, const long tp_type,
const long openmp_per_triplets, const long openmp_per_bands);
void ph3py_get_integration_weight_with_sigma(
double *iw, char *iw_zero, const double sigma, const double sigma_cutoff,
const double *frequency_points, const long num_band0,
const long (*triplets)[3], const long num_triplets,
const double *frequencies, const long num_band, const long tp_type);
long ph3py_get_grid_index_from_address(const long address[3],
const long mesh[3]);
void ph3py_get_gr_grid_addresses(long gr_grid_addresses[][3],
@ -297,38 +176,27 @@ long ph3py_get_reciprocal_rotations(long rec_rotations[48][3][3],
const long is_time_reversal);
long ph3py_transform_rotations(long (*transformed_rots)[3][3],
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
const long num_rot, const long D_diag[3],
const long Q[3][3]);
long ph3py_get_snf3x3(long D_diag[3],
long P[3][3],
long Q[3][3],
long ph3py_get_snf3x3(long D_diag[3], long P[3][3], long Q[3][3],
const long A[3][3]);
long ph3py_transform_rotations(long (*transformed_rots)[3][3],
const long (*rotations)[3][3],
const long num_rot,
const long D_diag[3],
const long num_rot, const long D_diag[3],
const long Q[3][3]);
long ph3py_get_ir_grid_map(long *ir_grid_map,
const long D_diag[3],
const long PS[3],
const long (*grg_rotations)[3][3],
long ph3py_get_ir_grid_map(long *ir_grid_map, const long D_diag[3],
const long PS[3], const long (*grg_rotations)[3][3],
const long num_rot);
long ph3py_get_bz_grid_addresses(long (*bz_grid_addresses)[3],
long *bz_map,
long *bzg2grg,
const long D_diag[3],
const long Q[3][3],
const long PS[3],
long ph3py_get_bz_grid_addresses(long (*bz_grid_addresses)[3], long *bz_map,
long *bzg2grg, const long D_diag[3],
const long Q[3][3], const long PS[3],
const double rec_lattice[3][3],
const long type);
long ph3py_rotate_bz_grid_index(const long bz_grid_index,
const long rotation[3][3],
const long (*bz_grid_addresses)[3],
const long *bz_map,
const long D_diag[3],
const long PS[3],
const long bz_grid_type);
const long *bz_map, const long D_diag[3],
const long PS[3], const long bz_grid_type);
void ph3py_symmetrize_collision_matrix(double *collision_matrix,
const long num_column,
const long num_temp,
@ -338,33 +206,20 @@ void ph3py_expand_collision_matrix(double *collision_matrix,
const long *ir_grid_points,
const long num_ir_gp,
const long num_grid_points,
const long num_rot,
const long num_sigma,
const long num_temp,
const long num_band);
long ph3py_get_neighboring_gird_points(long *relative_grid_points,
const long *grid_points,
const long (*relative_grid_address)[3],
const long mesh[3],
const long (*bz_grid_addresses)[3],
const long *bz_map,
const long bz_grid_type,
const long num_grid_points,
const long num_relative_grid_address);
const long num_rot, const long num_sigma,
const long num_temp, const long num_band);
long ph3py_get_neighboring_gird_points(
long *relative_grid_points, const long *grid_points,
const long (*relative_grid_address)[3], const long mesh[3],
const long (*bz_grid_addresses)[3], const long *bz_map,
const long bz_grid_type, const long num_grid_points,
const long num_relative_grid_address);
long ph3py_get_thm_integration_weights_at_grid_points(
double *iw,
const double *frequency_points,
const long num_band0,
const long num_band,
const long num_gp,
const long (*relative_grid_address)[4][3],
const long D_diag[3],
const long *grid_points,
const long (*bz_grid_addresses)[3],
const long *bz_map,
const long bz_grid_type,
const double *frequencies,
const long *gp2irgp_map,
const char function);
double *iw, const double *frequency_points, const long num_band0,
const long num_band, const long num_gp,
const long (*relative_grid_address)[4][3], const long D_diag[3],
const long *grid_points, const long (*bz_grid_addresses)[3],
const long *bz_map, const long bz_grid_type, const double *frequencies,
const long *gp2irgp_map, const char function);
#endif

View File

@ -39,13 +39,13 @@
/* It is assumed that number of dimensions is known for each array. */
typedef struct {
long dims[MAX_NUM_DIM];
long *data;
long dims[MAX_NUM_DIM];
long *data;
} Larray;
typedef struct {
int dims[MAX_NUM_DIM];
double *data;
int dims[MAX_NUM_DIM];
double *data;
} Darray;
#endif

View File

@ -32,24 +32,23 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include <math.h>
#include "phonoc_const.h"
#include "phonoc_utils.h"
#include <math.h>
#include "phonoc_const.h"
#define THZTOEVPARKB 47.992398658977166
#define INVSQRT2PI 0.3989422804014327
double phonoc_bose_einstein(const double x, const double t)
{
return 1.0 / (exp(THZTOEVPARKB * x / t) - 1);
double phonoc_bose_einstein(const double x, const double t) {
return 1.0 / (exp(THZTOEVPARKB * x / t) - 1);
}
double phonoc_gaussian(const double x, const double sigma)
{
return INVSQRT2PI / sigma * exp(-x * x / 2 / sigma / sigma);
double phonoc_gaussian(const double x, const double sigma) {
return INVSQRT2PI / sigma * exp(-x * x / 2 / sigma / sigma);
}
double phonoc_inv_sinh_occupation(const double x, const double t)
{
return 1.0 / sinh(x * THZTOEVPARKB / 2 / t);
double phonoc_inv_sinh_occupation(const double x, const double t) {
return 1.0 / sinh(x * THZTOEVPARKB / 2 / t);
}

1003
c/phonon.c

File diff suppressed because it is too large Load Diff

View File

@ -38,55 +38,27 @@
#include "dynmat.h"
#include "lapack_wrapper.h"
void phn_get_phonons_at_gridpoints(double *frequencies,
lapack_complex_double *eigenvectors,
char *phonon_done,
const long num_phonons,
const long *grid_points,
const long num_grid_points,
const long (*grid_address)[3],
const double QDinv[3][3],
const double *fc2,
const double (*svecs_fc2)[3],
const long (*multi_fc2)[2],
const long num_patom,
const long num_satom,
const double *masses_fc2,
const long *p2s_fc2,
const long *s2p_fc2,
const double unit_conversion_factor,
const double (*born)[3][3],
const double dielectric[3][3],
const double reciprocal_lattice[3][3],
const double *q_direction, /* must be pointer */
const double nac_factor,
const char uplo);
void phn_get_gonze_phonons_at_gridpoints(double *frequencies,
lapack_complex_double *eigenvectors,
char *phonon_done,
const long num_phonons,
const long *grid_points,
const long num_grid_points,
const long (*grid_address)[3],
const double QDinv[3][3],
const double *fc2,
const double (*svecs_fc2)[3],
const long (*multi_fc2)[2],
const double (*positions)[3],
const long num_patom,
const long num_satom,
const double *masses_fc2,
const long *p2s_fc2,
const long *s2p_fc2,
const double unit_conversion_factor,
const double (*born)[3][3],
const double dielectric[3][3],
const double reciprocal_lattice[3][3],
const double *q_direction, /* pointer */
const double nac_factor,
const double *dd_q0,
const double (*G_list)[3],
const long num_G_points,
const double lambda,
const char uplo);
void phn_get_phonons_at_gridpoints(
double *frequencies, lapack_complex_double *eigenvectors, char *phonon_done,
const long num_phonons, const long *grid_points, const long num_grid_points,
const long (*grid_address)[3], const double QDinv[3][3], const double *fc2,
const double (*svecs_fc2)[3], const long (*multi_fc2)[2],
const long num_patom, const long num_satom, const double *masses_fc2,
const long *p2s_fc2, const long *s2p_fc2,
const double unit_conversion_factor, const double (*born)[3][3],
const double dielectric[3][3], const double reciprocal_lattice[3][3],
const double *q_direction, /* must be pointer */
const double nac_factor, const char uplo);
void phn_get_gonze_phonons_at_gridpoints(
double *frequencies, lapack_complex_double *eigenvectors, char *phonon_done,
const long num_phonons, const long *grid_points, const long num_grid_points,
const long (*grid_address)[3], const double QDinv[3][3], const double *fc2,
const double (*svecs_fc2)[3], const long (*multi_fc2)[2],
const double (*positions)[3], const long num_patom, const long num_satom,
const double *masses_fc2, const long *p2s_fc2, const long *s2p_fc2,
const double unit_conversion_factor, const double (*born)[3][3],
const double dielectric[3][3], const double reciprocal_lattice[3][3],
const double *q_direction, /* pointer */
const double nac_factor, const double *dd_q0, const double (*G_list)[3],
const long num_G_points, const double lambda, const char uplo);
#endif

View File

@ -33,93 +33,36 @@
/* POSSIBILITY OF SUCH DAMAGE. */
#include "phononmod.h"
#include "lapack_wrapper.h"
#include "phonon.h"
void phmod_get_phonons_at_gridpoints(double *frequencies,
lapack_complex_double *eigenvectors,
char *phonon_done,
const long num_phonons,
const long *grid_points,
const long num_grid_points,
const long (*grid_address)[3],
const double QDinv[3][3],
const double *fc2,
const double (*svecs_fc2)[3],
const long (*multi_fc2)[2],
const double (*positions_fc2)[3],
const long num_patom,
const long num_satom,
const double *masses_fc2,
const long *p2s_fc2,
const long *s2p_fc2,
const double unit_conversion_factor,
const double (*born)[3][3],
const double dielectric[3][3],
const double reciprocal_lattice[3][3],
const double *q_direction, /* pointer */
const double nac_factor,
const double *dd_q0,
const double (*G_list)[3],
const long num_G_points,
const double lambda,
const char uplo)
{
if (!dd_q0)
{
phn_get_phonons_at_gridpoints(frequencies,
eigenvectors,
phonon_done,
num_phonons,
grid_points,
num_grid_points,
grid_address,
QDinv,
fc2,
svecs_fc2,
multi_fc2,
num_patom,
num_satom,
masses_fc2,
p2s_fc2,
s2p_fc2,
unit_conversion_factor,
born,
dielectric,
reciprocal_lattice,
q_direction,
nac_factor,
uplo);
}
else
{
phn_get_gonze_phonons_at_gridpoints(frequencies,
eigenvectors,
phonon_done,
num_phonons,
grid_points,
num_grid_points,
grid_address,
QDinv,
fc2,
svecs_fc2,
multi_fc2,
positions_fc2,
num_patom,
num_satom,
masses_fc2,
p2s_fc2,
s2p_fc2,
unit_conversion_factor,
born,
dielectric,
reciprocal_lattice,
q_direction,
nac_factor,
dd_q0,
G_list,
num_G_points,
lambda,
uplo);
}
void phmod_get_phonons_at_gridpoints(
double *frequencies, lapack_complex_double *eigenvectors, char *phonon_done,
const long num_phonons, const long *grid_points, const long num_grid_points,
const long (*grid_address)[3], const double QDinv[3][3], const double *fc2,
const double (*svecs_fc2)[3], const long (*multi_fc2)[2],
const double (*positions_fc2)[3], const long num_patom,
const long num_satom, const double *masses_fc2, const long *p2s_fc2,
const long *s2p_fc2, const double unit_conversion_factor,
const double (*born)[3][3], const double dielectric[3][3],
const double reciprocal_lattice[3][3],
const double *q_direction, /* pointer */
const double nac_factor, const double *dd_q0, const double (*G_list)[3],
const long num_G_points, const double lambda, const char uplo) {
if (!dd_q0) {
phn_get_phonons_at_gridpoints(
frequencies, eigenvectors, phonon_done, num_phonons, grid_points,
num_grid_points, grid_address, QDinv, fc2, svecs_fc2, multi_fc2,
num_patom, num_satom, masses_fc2, p2s_fc2, s2p_fc2,
unit_conversion_factor, born, dielectric, reciprocal_lattice,
q_direction, nac_factor, uplo);
} else {
phn_get_gonze_phonons_at_gridpoints(
frequencies, eigenvectors, phonon_done, num_phonons, grid_points,
num_grid_points, grid_address, QDinv, fc2, svecs_fc2, multi_fc2,
positions_fc2, num_patom, num_satom, masses_fc2, p2s_fc2, s2p_fc2,
unit_conversion_factor, born, dielectric, reciprocal_lattice,
q_direction, nac_factor, dd_q0, G_list, num_G_points, lambda, uplo);
}
}

View File

@ -37,33 +37,18 @@
#include "lapack_wrapper.h"
void phmod_get_phonons_at_gridpoints(double *frequencies,
lapack_complex_double *eigenvectors,
char *phonon_done,
const long num_phonons,
const long *grid_points,
const long num_grid_points,
const long (*grid_address)[3],
const double QDinv[3][3],
const double *fc2,
const double (*svecs_fc2)[3],
const long (*multi_fc2)[2],
const double (*positions_fc2)[3],
const long num_patom,
const long num_satom,
const double *masses_fc2,
const long *p2s_fc2,
const long *s2p_fc2,
const double unit_conversion_factor,
const double (*born)[3][3],
const double dielectric[3][3],
const double reciprocal_lattice[3][3],
const double *q_direction, /* pointer */
const double nac_factor,
const double *dd_q0,
const double (*G_list)[3],
const long num_G_points,
const double lambda,
const char uplo);
void phmod_get_phonons_at_gridpoints(
double *frequencies, lapack_complex_double *eigenvectors, char *phonon_done,
const long num_phonons, const long *grid_points, const long num_grid_points,
const long (*grid_address)[3], const double QDinv[3][3], const double *fc2,
const double (*svecs_fc2)[3], const long (*multi_fc2)[2],
const double (*positions_fc2)[3], const long num_patom,
const long num_satom, const double *masses_fc2, const long *p2s_fc2,
const long *s2p_fc2, const double unit_conversion_factor,
const double (*born)[3][3], const double dielectric[3][3],
const double reciprocal_lattice[3][3],
const double *q_direction, /* pointer */
const double nac_factor, const double *dd_q0, const double (*G_list)[3],
const long num_G_points, const double lambda, const char uplo);
#endif

View File

@ -32,454 +32,277 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include "pp_collision.h"
#include <stdio.h>
#include <stdlib.h>
#include "imag_self_energy_with_g.h"
#include "interaction.h"
#include "lapack_wrapper.h"
#include "phonoc_array.h"
#include "phonoc_utils.h"
#include "pp_collision.h"
#include "triplet.h"
#include "triplet_iw.h"
#include "lapack_wrapper.h"
static void get_collision(double *ise,
const long num_band0,
const long num_band,
const long num_temps,
const double *temperatures,
const double *g,
const char *g_zero,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long triplet[3],
const long triplet_weight,
const ConstBZGrid *bzgrid,
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const long *band_indices,
const long symmetrize_fc3_q,
const double cutoff_frequency,
const long openmp_per_triplets);
static void finalize_ise(double *imag_self_energy,
const double *ise,
static void get_collision(
double *ise, const long num_band0, const long num_band,
const long num_temps, const double *temperatures, const double *g,
const char *g_zero, const double *frequencies,
const lapack_complex_double *eigenvectors, const long triplet[3],
const long triplet_weight, const ConstBZGrid *bzgrid, const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2],
const double *masses, const long *p2s_map, const long *s2p_map,
const long *band_indices, const long symmetrize_fc3_q,
const double cutoff_frequency, const long openmp_per_triplets);
static void finalize_ise(double *imag_self_energy, const double *ise,
const long (*bz_grid_address)[3],
const long (*triplets)[3],
const long num_triplets,
const long num_temps,
const long num_band0,
const long (*triplets)[3], const long num_triplets,
const long num_temps, const long num_band0,
const long is_NU);
void ppc_get_pp_collision(double *imag_self_energy,
const long relative_grid_address[24][4][3], /* thm */
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long (*triplets)[3],
const long num_triplets,
const long *triplet_weights,
const ConstBZGrid *bzgrid,
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const Larray *band_indices,
const Darray *temperatures,
const long is_NU,
const long symmetrize_fc3_q,
const double cutoff_frequency)
{
long i;
long num_band, num_band0, num_band_prod, num_temps;
long openmp_per_triplets;
double *ise, *freqs_at_gp, *g;
char *g_zero;
long tp_relative_grid_address[2][24][4][3];
void ppc_get_pp_collision(
double *imag_self_energy,
const long relative_grid_address[24][4][3], /* thm */
const double *frequencies, const lapack_complex_double *eigenvectors,
const long (*triplets)[3], const long num_triplets,
const long *triplet_weights, const ConstBZGrid *bzgrid, const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2],
const double *masses, const long *p2s_map, const long *s2p_map,
const Larray *band_indices, const Darray *temperatures, const long is_NU,
const long symmetrize_fc3_q, const double cutoff_frequency) {
long i;
long num_band, num_band0, num_band_prod, num_temps;
long openmp_per_triplets;
double *ise, *freqs_at_gp, *g;
char *g_zero;
long tp_relative_grid_address[2][24][4][3];
ise = NULL;
freqs_at_gp = NULL;
g = NULL;
g_zero = NULL;
ise = NULL;
freqs_at_gp = NULL;
g = NULL;
g_zero = NULL;
num_band0 = band_indices->dims[0];
num_band = multi_dims[1] * 3;
num_band_prod = num_band0 * num_band * num_band;
num_temps = temperatures->dims[0];
ise = (double *)malloc(sizeof(double) * num_triplets * num_temps * num_band0);
freqs_at_gp = (double *)malloc(sizeof(double) * num_band0);
for (i = 0; i < num_band0; i++)
{
freqs_at_gp[i] = frequencies[triplets[0][0] * num_band + band_indices->data[i]];
}
num_band0 = band_indices->dims[0];
num_band = multi_dims[1] * 3;
num_band_prod = num_band0 * num_band * num_band;
num_temps = temperatures->dims[0];
ise =
(double *)malloc(sizeof(double) * num_triplets * num_temps * num_band0);
freqs_at_gp = (double *)malloc(sizeof(double) * num_band0);
for (i = 0; i < num_band0; i++) {
freqs_at_gp[i] =
frequencies[triplets[0][0] * num_band + band_indices->data[i]];
}
if (num_triplets > num_band)
{
openmp_per_triplets = 1;
}
else
{
openmp_per_triplets = 0;
}
if (num_triplets > num_band) {
openmp_per_triplets = 1;
} else {
openmp_per_triplets = 0;
}
tpl_set_relative_grid_address(tp_relative_grid_address,
relative_grid_address,
2);
tpl_set_relative_grid_address(tp_relative_grid_address,
relative_grid_address, 2);
#ifdef PHPYOPENMP
#pragma omp parallel for schedule(guided) private(g, g_zero) if (openmp_per_triplets)
#pragma omp parallel for schedule(guided) private( \
g, g_zero) if (openmp_per_triplets)
#endif
for (i = 0; i < num_triplets; i++)
{
g = (double *)malloc(sizeof(double) * 2 * num_band_prod);
g_zero = (char *)malloc(sizeof(char) * num_band_prod);
tpi_get_integration_weight(g,
g_zero,
freqs_at_gp, /* used as f0 */
num_band0,
tp_relative_grid_address,
triplets[i],
1,
bzgrid,
frequencies, /* used as f1 */
num_band,
frequencies, /* used as f2 */
num_band,
2,
1 - openmp_per_triplets);
for (i = 0; i < num_triplets; i++) {
g = (double *)malloc(sizeof(double) * 2 * num_band_prod);
g_zero = (char *)malloc(sizeof(char) * num_band_prod);
tpi_get_integration_weight(g, g_zero, freqs_at_gp, /* used as f0 */
num_band0, tp_relative_grid_address,
triplets[i], 1, bzgrid,
frequencies, /* used as f1 */
num_band, frequencies, /* used as f2 */
num_band, 2, 1 - openmp_per_triplets);
get_collision(ise + i * num_temps * num_band0,
num_band0,
num_band,
num_temps,
temperatures->data,
g,
g_zero,
frequencies,
eigenvectors,
triplets[i],
triplet_weights[i],
bzgrid,
fc3,
is_compact_fc3,
svecs,
multi_dims,
multiplicity,
masses,
p2s_map,
s2p_map,
band_indices->data,
symmetrize_fc3_q,
cutoff_frequency,
openmp_per_triplets);
get_collision(ise + i * num_temps * num_band0, num_band0, num_band,
num_temps, temperatures->data, g, g_zero, frequencies,
eigenvectors, triplets[i], triplet_weights[i], bzgrid,
fc3, is_compact_fc3, svecs, multi_dims, multiplicity,
masses, p2s_map, s2p_map, band_indices->data,
symmetrize_fc3_q, cutoff_frequency, openmp_per_triplets);
free(g_zero);
g_zero = NULL;
free(g);
g = NULL;
}
free(g_zero);
g_zero = NULL;
free(g);
g = NULL;
}
finalize_ise(imag_self_energy,
ise,
bzgrid->addresses,
triplets,
num_triplets,
num_temps,
num_band0,
is_NU);
finalize_ise(imag_self_energy, ise, bzgrid->addresses, triplets,
num_triplets, num_temps, num_band0, is_NU);
free(freqs_at_gp);
freqs_at_gp = NULL;
free(ise);
ise = NULL;
free(freqs_at_gp);
freqs_at_gp = NULL;
free(ise);
ise = NULL;
}
void ppc_get_pp_collision_with_sigma(
double *imag_self_energy,
const double sigma,
const double sigma_cutoff,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long (*triplets)[3],
const long num_triplets,
const long *triplet_weights,
const ConstBZGrid *bzgrid,
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const Larray *band_indices,
const Darray *temperatures,
const long is_NU,
const long symmetrize_fc3_q,
const double cutoff_frequency)
{
long i;
long num_band, num_band0, num_band_prod, num_temps;
long openmp_per_triplets, const_adrs_shift;
double cutoff;
double *ise, *freqs_at_gp, *g;
char *g_zero;
double *imag_self_energy, const double sigma, const double sigma_cutoff,
const double *frequencies, const lapack_complex_double *eigenvectors,
const long (*triplets)[3], const long num_triplets,
const long *triplet_weights, const ConstBZGrid *bzgrid, const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2],
const double *masses, const long *p2s_map, const long *s2p_map,
const Larray *band_indices, const Darray *temperatures, const long is_NU,
const long symmetrize_fc3_q, const double cutoff_frequency) {
long i;
long num_band, num_band0, num_band_prod, num_temps;
long openmp_per_triplets, const_adrs_shift;
double cutoff;
double *ise, *freqs_at_gp, *g;
char *g_zero;
ise = NULL;
freqs_at_gp = NULL;
g = NULL;
g_zero = NULL;
ise = NULL;
freqs_at_gp = NULL;
g = NULL;
g_zero = NULL;
num_band0 = band_indices->dims[0];
num_band = multi_dims[1] * 3;
num_band_prod = num_band0 * num_band * num_band;
num_temps = temperatures->dims[0];
const_adrs_shift = num_band_prod;
num_band0 = band_indices->dims[0];
num_band = multi_dims[1] * 3;
num_band_prod = num_band0 * num_band * num_band;
num_temps = temperatures->dims[0];
const_adrs_shift = num_band_prod;
ise = (double *)malloc(sizeof(double) * num_triplets * num_temps * num_band0);
freqs_at_gp = (double *)malloc(sizeof(double) * num_band0);
for (i = 0; i < num_band0; i++)
{
freqs_at_gp[i] = frequencies[triplets[0][0] * num_band +
band_indices->data[i]];
}
ise =
(double *)malloc(sizeof(double) * num_triplets * num_temps * num_band0);
freqs_at_gp = (double *)malloc(sizeof(double) * num_band0);
for (i = 0; i < num_band0; i++) {
freqs_at_gp[i] =
frequencies[triplets[0][0] * num_band + band_indices->data[i]];
}
if (num_triplets > num_band)
{
openmp_per_triplets = 1;
}
else
{
openmp_per_triplets = 0;
}
if (num_triplets > num_band) {
openmp_per_triplets = 1;
} else {
openmp_per_triplets = 0;
}
cutoff = sigma * sigma_cutoff;
cutoff = sigma * sigma_cutoff;
#ifdef PHPYOPENMP
#pragma omp parallel for schedule(guided) private(g, g_zero) if (openmp_per_triplets)
#pragma omp parallel for schedule(guided) private( \
g, g_zero) if (openmp_per_triplets)
#endif
for (i = 0; i < num_triplets; i++)
{
g = (double *)malloc(sizeof(double) * 2 * num_band_prod);
g_zero = (char *)malloc(sizeof(char) * num_band_prod);
tpi_get_integration_weight_with_sigma(g,
g_zero,
sigma,
cutoff,
freqs_at_gp,
num_band0,
triplets[i],
const_adrs_shift,
frequencies,
num_band,
2,
0);
for (i = 0; i < num_triplets; i++) {
g = (double *)malloc(sizeof(double) * 2 * num_band_prod);
g_zero = (char *)malloc(sizeof(char) * num_band_prod);
tpi_get_integration_weight_with_sigma(
g, g_zero, sigma, cutoff, freqs_at_gp, num_band0, triplets[i],
const_adrs_shift, frequencies, num_band, 2, 0);
get_collision(ise + i * num_temps * num_band0,
num_band0,
num_band,
num_temps,
temperatures->data,
g,
g_zero,
frequencies,
eigenvectors,
triplets[i],
triplet_weights[i],
bzgrid,
fc3,
is_compact_fc3,
svecs,
multi_dims,
multiplicity,
masses,
p2s_map,
s2p_map,
band_indices->data,
symmetrize_fc3_q,
cutoff_frequency,
openmp_per_triplets);
get_collision(ise + i * num_temps * num_band0, num_band0, num_band,
num_temps, temperatures->data, g, g_zero, frequencies,
eigenvectors, triplets[i], triplet_weights[i], bzgrid,
fc3, is_compact_fc3, svecs, multi_dims, multiplicity,
masses, p2s_map, s2p_map, band_indices->data,
symmetrize_fc3_q, cutoff_frequency, openmp_per_triplets);
free(g_zero);
g_zero = NULL;
free(g);
g = NULL;
}
free(g_zero);
g_zero = NULL;
free(g);
g = NULL;
}
finalize_ise(imag_self_energy,
ise,
bzgrid->addresses,
triplets,
num_triplets,
num_temps,
num_band0,
is_NU);
finalize_ise(imag_self_energy, ise, bzgrid->addresses, triplets,
num_triplets, num_temps, num_band0, is_NU);
free(freqs_at_gp);
freqs_at_gp = NULL;
free(ise);
ise = NULL;
free(freqs_at_gp);
freqs_at_gp = NULL;
free(ise);
ise = NULL;
}
static void get_collision(double *ise,
const long num_band0,
const long num_band,
const long num_temps,
const double *temperatures,
const double *g,
const char *g_zero,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long triplet[3],
const long triplet_weight,
const ConstBZGrid *bzgrid,
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const long *band_indices,
const long symmetrize_fc3_q,
const double cutoff_frequency,
const long openmp_per_triplets)
{
long i;
long num_band_prod, num_g_pos;
double *fc3_normal_squared;
long(*g_pos)[4];
static void get_collision(
double *ise, const long num_band0, const long num_band,
const long num_temps, const double *temperatures, const double *g,
const char *g_zero, const double *frequencies,
const lapack_complex_double *eigenvectors, const long triplet[3],
const long triplet_weight, const ConstBZGrid *bzgrid, const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2],
const double *masses, const long *p2s_map, const long *s2p_map,
const long *band_indices, const long symmetrize_fc3_q,
const double cutoff_frequency, const long openmp_per_triplets) {
long i;
long num_band_prod, num_g_pos;
double *fc3_normal_squared;
long(*g_pos)[4];
fc3_normal_squared = NULL;
g_pos = NULL;
fc3_normal_squared = NULL;
g_pos = NULL;
num_band_prod = num_band0 * num_band * num_band;
fc3_normal_squared = (double *)malloc(sizeof(double) * num_band_prod);
g_pos = (long(*)[4])malloc(sizeof(long[4]) * num_band_prod);
num_band_prod = num_band0 * num_band * num_band;
fc3_normal_squared = (double *)malloc(sizeof(double) * num_band_prod);
g_pos = (long(*)[4])malloc(sizeof(long[4]) * num_band_prod);
for (i = 0; i < num_band_prod; i++)
{
fc3_normal_squared[i] = 0;
}
for (i = 0; i < num_band_prod; i++) {
fc3_normal_squared[i] = 0;
}
num_g_pos = ise_set_g_pos(g_pos,
num_band0,
num_band,
g_zero);
num_g_pos = ise_set_g_pos(g_pos, num_band0, num_band, g_zero);
itr_get_interaction_at_triplet(
fc3_normal_squared,
num_band0,
num_band,
g_pos,
num_g_pos,
frequencies,
eigenvectors,
triplet,
bzgrid,
fc3,
is_compact_fc3,
svecs,
multi_dims,
multiplicity,
masses,
p2s_map,
s2p_map,
band_indices,
symmetrize_fc3_q,
cutoff_frequency,
0,
0,
1 - openmp_per_triplets);
itr_get_interaction_at_triplet(
fc3_normal_squared, num_band0, num_band, g_pos, num_g_pos, frequencies,
eigenvectors, triplet, bzgrid, fc3, is_compact_fc3, svecs, multi_dims,
multiplicity, masses, p2s_map, s2p_map, band_indices, symmetrize_fc3_q,
cutoff_frequency, 0, 0, 1 - openmp_per_triplets);
ise_imag_self_energy_at_triplet(
ise,
num_band0,
num_band,
fc3_normal_squared,
frequencies,
triplet,
triplet_weight,
g,
g + num_band_prod,
g_pos,
num_g_pos,
temperatures,
num_temps,
cutoff_frequency,
1 - openmp_per_triplets,
0);
ise_imag_self_energy_at_triplet(
ise, num_band0, num_band, fc3_normal_squared, frequencies, triplet,
triplet_weight, g, g + num_band_prod, g_pos, num_g_pos, temperatures,
num_temps, cutoff_frequency, 1 - openmp_per_triplets, 0);
free(fc3_normal_squared);
fc3_normal_squared = NULL;
free(g_pos);
g_pos = NULL;
free(fc3_normal_squared);
fc3_normal_squared = NULL;
free(g_pos);
g_pos = NULL;
}
static void finalize_ise(double *imag_self_energy,
const double *ise,
static void finalize_ise(double *imag_self_energy, const double *ise,
const long (*bz_grid_addresses)[3],
const long (*triplets)[3],
const long num_triplets,
const long num_temps,
const long num_band0,
const long is_NU)
{
long i, j, k;
long is_N;
const long (*triplets)[3], const long num_triplets,
const long num_temps, const long num_band0,
const long is_NU) {
long i, j, k;
long is_N;
if (is_NU)
{
for (i = 0; i < 2 * num_temps * num_band0; i++)
{
imag_self_energy[i] = 0;
}
for (i = 0; i < num_triplets; i++)
{
is_N = tpl_is_N(triplets[i], bz_grid_addresses);
for (j = 0; j < num_temps; j++)
{
for (k = 0; k < num_band0; k++)
{
if (is_N)
{
imag_self_energy[j * num_band0 + k] +=
ise[i * num_temps * num_band0 + j * num_band0 + k];
}
else
{
imag_self_energy[num_temps * num_band0 + j * num_band0 + k] +=
ise[i * num_temps * num_band0 + j * num_band0 + k];
}
if (is_NU) {
for (i = 0; i < 2 * num_temps * num_band0; i++) {
imag_self_energy[i] = 0;
}
}
}
}
else
{
for (i = 0; i < num_temps * num_band0; i++)
{
imag_self_energy[i] = 0;
}
for (i = 0; i < num_triplets; i++)
{
for (j = 0; j < num_temps; j++)
{
for (k = 0; k < num_band0; k++)
{
imag_self_energy[j * num_band0 + k] +=
ise[i * num_temps * num_band0 + j * num_band0 + k];
for (i = 0; i < num_triplets; i++) {
is_N = tpl_is_N(triplets[i], bz_grid_addresses);
for (j = 0; j < num_temps; j++) {
for (k = 0; k < num_band0; k++) {
if (is_N) {
imag_self_energy[j * num_band0 + k] +=
ise[i * num_temps * num_band0 + j * num_band0 + k];
} else {
imag_self_energy[num_temps * num_band0 + j * num_band0 +
k] +=
ise[i * num_temps * num_band0 + j * num_band0 + k];
}
}
}
}
} else {
for (i = 0; i < num_temps * num_band0; i++) {
imag_self_energy[i] = 0;
}
for (i = 0; i < num_triplets; i++) {
for (j = 0; j < num_temps; j++) {
for (k = 0; k < num_band0; k++) {
imag_self_energy[j * num_band0 + k] +=
ise[i * num_temps * num_band0 + j * num_band0 + k];
}
}
}
}
}
}
}

View File

@ -39,49 +39,26 @@
#include "lapack_wrapper.h"
#include "phonoc_array.h"
void ppc_get_pp_collision(double *imag_self_energy,
const long relative_grid_address[24][4][3], /* thm */
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long (*triplets)[3],
const long num_triplets,
const long *triplet_weights,
const ConstBZGrid *bzgrid,
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const Larray *band_indices,
const Darray *temperatures,
const long is_NU,
const long symmetrize_fc3_q,
const double cutoff_frequency);
void ppc_get_pp_collision(
double *imag_self_energy,
const long relative_grid_address[24][4][3], /* thm */
const double *frequencies, const lapack_complex_double *eigenvectors,
const long (*triplets)[3], const long num_triplets,
const long *triplet_weights, const ConstBZGrid *bzgrid, const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2],
const double *masses, const long *p2s_map, const long *s2p_map,
const Larray *band_indices, const Darray *temperatures, const long is_NU,
const long symmetrize_fc3_q, const double cutoff_frequency);
void ppc_get_pp_collision_with_sigma(
double *imag_self_energy,
const double sigma,
const double sigma_cutoff,
const double *frequencies,
const lapack_complex_double *eigenvectors,
const long (*triplets)[3],
const long num_triplets,
const long *triplet_weights,
const ConstBZGrid *bzgrid,
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const double *masses,
const long *p2s_map,
const long *s2p_map,
const Larray *band_indices,
const Darray *temperatures,
const long is_NU,
const long symmetrize_fc3_q,
const double cutoff_frequency);
double *imag_self_energy, const double sigma, const double sigma_cutoff,
const double *frequencies, const lapack_complex_double *eigenvectors,
const long (*triplets)[3], const long num_triplets,
const long *triplet_weights, const ConstBZGrid *bzgrid, const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2],
const double *masses, const long *p2s_map, const long *s2p_map,
const Larray *band_indices, const Darray *temperatures, const long is_NU,
const long symmetrize_fc3_q, const double cutoff_frequency);
#endif

View File

@ -32,263 +32,191 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include <stdlib.h>
#include "real_self_energy.h"
#include <math.h>
#include <stdlib.h>
#include "phonoc_array.h"
#include "phonoc_utils.h"
#include "real_self_energy.h"
#include "real_to_reciprocal.h"
static double get_real_self_energy_at_band(const long band_index,
const Darray *fc3_normal_squared,
const double fpoint,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const double epsilon,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency);
static double sum_real_self_energy_at_band(const long num_band,
const double *fc3_normal_squared,
const double fpoint,
const double *freqs1,
const double *freqs2,
const double epsilon,
const double temperature,
const double cutoff_frequency);
static double sum_real_self_energy_at_band_0K(const long num_band,
const double *fc3_normal_squared,
const double fpoint,
const double *freqs1,
const double *freqs2,
const double epsilon,
const double cutoff_frequency);
static double get_real_self_energy_at_band(
const long band_index, const Darray *fc3_normal_squared,
const double fpoint, const double *frequencies, const long (*triplets)[3],
const long *triplet_weights, const double epsilon, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency);
static double sum_real_self_energy_at_band(
const long num_band, const double *fc3_normal_squared, const double fpoint,
const double *freqs1, const double *freqs2, const double epsilon,
const double temperature, const double cutoff_frequency);
static double sum_real_self_energy_at_band_0K(
const long num_band, const double *fc3_normal_squared, const double fpoint,
const double *freqs1, const double *freqs2, const double epsilon,
const double cutoff_frequency);
void rse_get_real_self_energy_at_bands(double *real_self_energy,
const Darray *fc3_normal_squared,
const long *band_indices,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const double epsilon,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency)
{
long i, num_band0, num_band, gp0;
double fpoint;
void rse_get_real_self_energy_at_bands(
double *real_self_energy, const Darray *fc3_normal_squared,
const long *band_indices, const double *frequencies,
const long (*triplets)[3], const long *triplet_weights,
const double epsilon, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency) {
long i, num_band0, num_band, gp0;
double fpoint;
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
gp0 = triplets[0][0];
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
gp0 = triplets[0][0];
/* num_band0 and num_band_indices have to be same. */
for (i = 0; i < num_band0; i++)
{
fpoint = frequencies[gp0 * num_band + band_indices[i]];
if (fpoint < cutoff_frequency)
{
real_self_energy[i] = 0;
/* num_band0 and num_band_indices have to be same. */
for (i = 0; i < num_band0; i++) {
fpoint = frequencies[gp0 * num_band + band_indices[i]];
if (fpoint < cutoff_frequency) {
real_self_energy[i] = 0;
} else {
real_self_energy[i] = get_real_self_energy_at_band(
i, fc3_normal_squared, fpoint, frequencies, triplets,
triplet_weights, epsilon, temperature, unit_conversion_factor,
cutoff_frequency);
}
}
else
{
real_self_energy[i] =
get_real_self_energy_at_band(i,
fc3_normal_squared,
fpoint,
frequencies,
triplets,
triplet_weights,
epsilon,
temperature,
unit_conversion_factor,
cutoff_frequency);
}
}
}
void rse_get_real_self_energy_at_frequency_point(
double *real_self_energy,
const double frequency_point,
const Darray *fc3_normal_squared,
const long *band_indices,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const double epsilon,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency)
{
long i, num_band0;
double *real_self_energy, const double frequency_point,
const Darray *fc3_normal_squared, const long *band_indices,
const double *frequencies, const long (*triplets)[3],
const long *triplet_weights, const double epsilon, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency) {
long i, num_band0;
num_band0 = fc3_normal_squared->dims[1];
num_band0 = fc3_normal_squared->dims[1];
/* num_band0 and num_band_indices have to be same. */
for (i = 0; i < num_band0; i++)
{
if (frequency_point < cutoff_frequency)
{
real_self_energy[i] = 0;
/* num_band0 and num_band_indices have to be same. */
for (i = 0; i < num_band0; i++) {
if (frequency_point < cutoff_frequency) {
real_self_energy[i] = 0;
} else {
real_self_energy[i] = get_real_self_energy_at_band(
i, fc3_normal_squared, frequency_point, frequencies, triplets,
triplet_weights, epsilon, temperature, unit_conversion_factor,
cutoff_frequency);
}
}
else
{
real_self_energy[i] =
get_real_self_energy_at_band(i,
fc3_normal_squared,
frequency_point,
frequencies,
triplets,
triplet_weights,
epsilon,
temperature,
unit_conversion_factor,
cutoff_frequency);
}
}
}
static double get_real_self_energy_at_band(const long band_index,
const Darray *fc3_normal_squared,
const double fpoint,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const double epsilon,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency)
{
long i, num_triplets, num_band0, num_band, gp1, gp2;
double shift;
static double get_real_self_energy_at_band(
const long band_index, const Darray *fc3_normal_squared,
const double fpoint, const double *frequencies, const long (*triplets)[3],
const long *triplet_weights, const double epsilon, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency) {
long i, num_triplets, num_band0, num_band, gp1, gp2;
double shift;
num_triplets = fc3_normal_squared->dims[0];
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
num_triplets = fc3_normal_squared->dims[0];
num_band0 = fc3_normal_squared->dims[1];
num_band = fc3_normal_squared->dims[2];
shift = 0;
shift = 0;
#ifdef PHPYOPENMP
#pragma omp parallel for private(gp1, gp2) reduction(+ \
: shift)
#pragma omp parallel for private(gp1, gp2) reduction(+ : shift)
#endif
for (i = 0; i < num_triplets; i++)
{
gp1 = triplets[i][1];
gp2 = triplets[i][2];
if (temperature > 0)
{
shift +=
sum_real_self_energy_at_band(num_band,
fc3_normal_squared->data +
i * num_band0 * num_band * num_band +
band_index * num_band * num_band,
fpoint,
frequencies + gp1 * num_band,
frequencies + gp2 * num_band,
epsilon,
temperature,
cutoff_frequency) *
triplet_weights[i] * unit_conversion_factor;
}
else
{
shift +=
sum_real_self_energy_at_band_0K(num_band,
fc3_normal_squared->data +
i * num_band0 * num_band * num_band +
band_index * num_band * num_band,
fpoint,
frequencies + gp1 * num_band,
frequencies + gp2 * num_band,
epsilon,
cutoff_frequency) *
triplet_weights[i] * unit_conversion_factor;
}
}
return shift;
}
static double sum_real_self_energy_at_band(const long num_band,
const double *fc3_normal_squared,
const double fpoint,
const double *freqs1,
const double *freqs2,
const double epsilon,
const double temperature,
const double cutoff_frequency)
{
long i, j;
double n1, n2, f1, f2, f3, f4, shift;
/* double sum; */
shift = 0;
for (i = 0; i < num_band; i++)
{
if (freqs1[i] > cutoff_frequency)
{
n1 = phonoc_bose_einstein(freqs1[i], temperature);
for (j = 0; j < num_band; j++)
{
if (freqs2[j] > cutoff_frequency)
{
n2 = phonoc_bose_einstein(freqs2[j], temperature);
f1 = fpoint + freqs1[i] + freqs2[j];
f2 = fpoint - freqs1[i] - freqs2[j];
f3 = fpoint - freqs1[i] + freqs2[j];
f4 = fpoint + freqs1[i] - freqs2[j];
/* sum = 0;
* if (fabs(f1) > epsilon) {
* sum -= (n1 + n2 + 1) / f1;
* }
* if (fabs(f2) > epsilon) {
* sum += (n1 + n2 + 1) / f2;
* }
* if (fabs(f3) > epsilon) {
* sum -= (n1 - n2) / f3;
* }
* if (fabs(f4) > epsilon) {
* sum += (n1 - n2) / f4;
* }
* shift += sum * fc3_normal_squared[i * num_band + j]; */
shift += (-(n1 + n2 + 1) * f1 / (f1 * f1 + epsilon * epsilon) + (n1 + n2 + 1) * f2 / (f2 * f2 + epsilon * epsilon) - (n1 - n2) * f3 / (f3 * f3 + epsilon * epsilon) + (n1 - n2) * f4 / (f4 * f4 + epsilon * epsilon)) *
fc3_normal_squared[i * num_band + j];
for (i = 0; i < num_triplets; i++) {
gp1 = triplets[i][1];
gp2 = triplets[i][2];
if (temperature > 0) {
shift += sum_real_self_energy_at_band(
num_band,
fc3_normal_squared->data +
i * num_band0 * num_band * num_band +
band_index * num_band * num_band,
fpoint, frequencies + gp1 * num_band,
frequencies + gp2 * num_band, epsilon, temperature,
cutoff_frequency) *
triplet_weights[i] * unit_conversion_factor;
} else {
shift +=
sum_real_self_energy_at_band_0K(
num_band,
fc3_normal_squared->data +
i * num_band0 * num_band * num_band +
band_index * num_band * num_band,
fpoint, frequencies + gp1 * num_band,
frequencies + gp2 * num_band, epsilon, cutoff_frequency) *
triplet_weights[i] * unit_conversion_factor;
}
}
}
}
return shift;
return shift;
}
static double sum_real_self_energy_at_band_0K(const long num_band,
const double *fc3_normal_squared,
const double fpoint,
const double *freqs1,
const double *freqs2,
const double epsilon,
const double cutoff_frequency)
{
long i, j;
double f1, f2, shift;
static double sum_real_self_energy_at_band(
const long num_band, const double *fc3_normal_squared, const double fpoint,
const double *freqs1, const double *freqs2, const double epsilon,
const double temperature, const double cutoff_frequency) {
long i, j;
double n1, n2, f1, f2, f3, f4, shift;
/* double sum; */
shift = 0;
for (i = 0; i < num_band; i++)
{
if (freqs1[i] > cutoff_frequency)
{
for (j = 0; j < num_band; j++)
{
if (freqs2[j] > cutoff_frequency)
{
f1 = fpoint + freqs1[i] + freqs2[j];
f2 = fpoint - freqs1[i] - freqs2[j];
shift += (-1 * f1 / (f1 * f1 + epsilon * epsilon) + 1 * f2 / (f2 * f2 + epsilon * epsilon)) *
fc3_normal_squared[i * num_band + j];
shift = 0;
for (i = 0; i < num_band; i++) {
if (freqs1[i] > cutoff_frequency) {
n1 = phonoc_bose_einstein(freqs1[i], temperature);
for (j = 0; j < num_band; j++) {
if (freqs2[j] > cutoff_frequency) {
n2 = phonoc_bose_einstein(freqs2[j], temperature);
f1 = fpoint + freqs1[i] + freqs2[j];
f2 = fpoint - freqs1[i] - freqs2[j];
f3 = fpoint - freqs1[i] + freqs2[j];
f4 = fpoint + freqs1[i] - freqs2[j];
/* sum = 0;
* if (fabs(f1) > epsilon) {
* sum -= (n1 + n2 + 1) / f1;
* }
* if (fabs(f2) > epsilon) {
* sum += (n1 + n2 + 1) / f2;
* }
* if (fabs(f3) > epsilon) {
* sum -= (n1 - n2) / f3;
* }
* if (fabs(f4) > epsilon) {
* sum += (n1 - n2) / f4;
* }
* shift += sum * fc3_normal_squared[i * num_band + j]; */
shift +=
(-(n1 + n2 + 1) * f1 / (f1 * f1 + epsilon * epsilon) +
(n1 + n2 + 1) * f2 / (f2 * f2 + epsilon * epsilon) -
(n1 - n2) * f3 / (f3 * f3 + epsilon * epsilon) +
(n1 - n2) * f4 / (f4 * f4 + epsilon * epsilon)) *
fc3_normal_squared[i * num_band + j];
}
}
}
}
}
}
return shift;
return shift;
}
static double sum_real_self_energy_at_band_0K(
const long num_band, const double *fc3_normal_squared, const double fpoint,
const double *freqs1, const double *freqs2, const double epsilon,
const double cutoff_frequency) {
long i, j;
double f1, f2, shift;
shift = 0;
for (i = 0; i < num_band; i++) {
if (freqs1[i] > cutoff_frequency) {
for (j = 0; j < num_band; j++) {
if (freqs2[j] > cutoff_frequency) {
f1 = fpoint + freqs1[i] + freqs2[j];
f2 = fpoint - freqs1[i] - freqs2[j];
shift += (-1 * f1 / (f1 * f1 + epsilon * epsilon) +
1 * f2 / (f2 * f2 + epsilon * epsilon)) *
fc3_normal_squared[i * num_band + j];
}
}
}
}
return shift;
}

View File

@ -39,25 +39,15 @@
#endif
void rse_get_real_self_energy_at_bands(double *real_self_energy,
const Darray *fc3_normal_squared,
const long *band_indices,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const double epsilon,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency);
void rse_get_real_self_energy_at_bands(
double *real_self_energy, const Darray *fc3_normal_squared,
const long *band_indices, const double *frequencies,
const long (*triplets)[3], const long *triplet_weights,
const double epsilon, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency);
void rse_get_real_self_energy_at_frequency_point(
double *real_self_energy,
const double frequency_point,
const Darray *fc3_normal_squared,
const long *band_indices,
const double *frequencies,
const long (*triplets)[3],
const long *triplet_weights,
const double epsilon,
const double temperature,
const double unit_conversion_factor,
const double cutoff_frequency);
double *real_self_energy, const double frequency_point,
const Darray *fc3_normal_squared, const long *band_indices,
const double *frequencies, const long (*triplets)[3],
const long *triplet_weights, const double epsilon, const double temperature,
const double unit_conversion_factor, const double cutoff_frequency);

View File

@ -32,337 +32,241 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include "real_to_reciprocal.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "lapack_wrapper.h"
#include "phonoc_array.h"
#include "phonoc_const.h"
#include "real_to_reciprocal.h"
#include "lapack_wrapper.h"
static void
real_to_reciprocal_single_thread(lapack_complex_double *fc3_reciprocal,
const double q_vecs[3][3],
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s_map,
const long *s2p_map);
static void
real_to_reciprocal_openmp(lapack_complex_double *fc3_reciprocal,
const double q_vecs[3][3],
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s_map,
const long *s2p_map);
static void real_to_reciprocal_elements(lapack_complex_double *fc3_rec_elem,
const double q_vecs[3][3],
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s,
const long *s2p,
const long pi0,
const long pi1,
const long pi2);
static void real_to_reciprocal_single_thread(
lapack_complex_double *fc3_reciprocal, const double q_vecs[3][3],
const double *fc3, const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2],
const long *p2s_map, const long *s2p_map);
static void real_to_reciprocal_openmp(
lapack_complex_double *fc3_reciprocal, const double q_vecs[3][3],
const double *fc3, const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2],
const long *p2s_map, const long *s2p_map);
static void real_to_reciprocal_elements(
lapack_complex_double *fc3_rec_elem, const double q_vecs[3][3],
const double *fc3, const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2], const long *p2s,
const long *s2p, const long pi0, const long pi1, const long pi2);
static lapack_complex_double get_phase_factor(const double q[3][3],
const long qi,
const double (*svecs)[3],
const long multi[2]);
static lapack_complex_double
get_pre_phase_factor(const long i_patom,
const double q_vecs[3][3],
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s_map);
static lapack_complex_double get_pre_phase_factor(const long i_patom,
const double q_vecs[3][3],
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s_map);
/* fc3_reciprocal[num_patom, num_patom, num_patom, 3, 3, 3] */
void r2r_real_to_reciprocal(lapack_complex_double *fc3_reciprocal,
const double q_vecs[3][3],
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const double q_vecs[3][3], const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s_map,
const long *s2p_map,
const long openmp_at_bands)
{
if (openmp_at_bands)
{
real_to_reciprocal_openmp(fc3_reciprocal,
q_vecs,
fc3,
is_compact_fc3,
svecs,
multi_dims,
multiplicity,
p2s_map,
s2p_map);
}
else
{
real_to_reciprocal_single_thread(fc3_reciprocal,
q_vecs,
fc3,
is_compact_fc3,
svecs,
multi_dims,
multiplicity,
p2s_map,
s2p_map);
}
}
static void
real_to_reciprocal_single_thread(lapack_complex_double *fc3_reciprocal,
const double q_vecs[3][3],
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s_map,
const long *s2p_map)
{
long i, j, k, l, m, n;
long num_patom, num_band;
lapack_complex_double pre_phase_factor, fc3_rec_elem[27];
num_patom = multi_dims[1];
num_band = num_patom * 3;
for (i = 0; i < num_patom; i++)
{
pre_phase_factor = get_pre_phase_factor(
i, q_vecs, svecs, multi_dims, multiplicity, p2s_map);
for (j = 0; j < num_patom; j++)
{
for (k = 0; k < num_patom; k++)
{
real_to_reciprocal_elements(fc3_rec_elem,
q_vecs,
fc3,
is_compact_fc3,
svecs,
multi_dims,
multiplicity,
p2s_map,
s2p_map,
i, j, k);
for (l = 0; l < 3; l++)
{
for (m = 0; m < 3; m++)
{
for (n = 0; n < 3; n++)
{
fc3_reciprocal[(i * 3 + l) * num_band * num_band + (j * 3 + m) * num_band + k * 3 + n] =
phonoc_complex_prod(fc3_rec_elem[l * 9 + m * 3 + n], pre_phase_factor);
}
}
}
}
const long (*multiplicity)[2], const long *p2s_map,
const long *s2p_map, const long openmp_at_bands) {
if (openmp_at_bands) {
real_to_reciprocal_openmp(fc3_reciprocal, q_vecs, fc3, is_compact_fc3,
svecs, multi_dims, multiplicity, p2s_map,
s2p_map);
} else {
real_to_reciprocal_single_thread(fc3_reciprocal, q_vecs, fc3,
is_compact_fc3, svecs, multi_dims,
multiplicity, p2s_map, s2p_map);
}
}
}
static void
real_to_reciprocal_openmp(lapack_complex_double *fc3_reciprocal,
const double q_vecs[3][3],
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s_map,
const long *s2p_map)
{
long i, j, k, l, m, n, jk;
long num_patom, num_band;
lapack_complex_double pre_phase_factor, fc3_rec_elem[27];
static void real_to_reciprocal_single_thread(
lapack_complex_double *fc3_reciprocal, const double q_vecs[3][3],
const double *fc3, const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2],
const long *p2s_map, const long *s2p_map) {
long i, j, k, l, m, n;
long num_patom, num_band;
lapack_complex_double pre_phase_factor, fc3_rec_elem[27];
num_patom = multi_dims[1];
num_band = num_patom * 3;
num_patom = multi_dims[1];
num_band = num_patom * 3;
for (i = 0; i < num_patom; i++)
{
pre_phase_factor = get_pre_phase_factor(
i, q_vecs, svecs, multi_dims, multiplicity, p2s_map);
for (i = 0; i < num_patom; i++) {
pre_phase_factor = get_pre_phase_factor(i, q_vecs, svecs, multi_dims,
multiplicity, p2s_map);
for (j = 0; j < num_patom; j++) {
for (k = 0; k < num_patom; k++) {
real_to_reciprocal_elements(
fc3_rec_elem, q_vecs, fc3, is_compact_fc3, svecs,
multi_dims, multiplicity, p2s_map, s2p_map, i, j, k);
for (l = 0; l < 3; l++) {
for (m = 0; m < 3; m++) {
for (n = 0; n < 3; n++) {
fc3_reciprocal[(i * 3 + l) * num_band * num_band +
(j * 3 + m) * num_band + k * 3 + n] =
phonoc_complex_prod(
fc3_rec_elem[l * 9 + m * 3 + n],
pre_phase_factor);
}
}
}
}
}
}
}
static void real_to_reciprocal_openmp(
lapack_complex_double *fc3_reciprocal, const double q_vecs[3][3],
const double *fc3, const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2],
const long *p2s_map, const long *s2p_map) {
long i, j, k, l, m, n, jk;
long num_patom, num_band;
lapack_complex_double pre_phase_factor, fc3_rec_elem[27];
num_patom = multi_dims[1];
num_band = num_patom * 3;
for (i = 0; i < num_patom; i++) {
pre_phase_factor = get_pre_phase_factor(i, q_vecs, svecs, multi_dims,
multiplicity, p2s_map);
#ifdef PHPYOPENMP
#pragma omp parallel for private(j, k, l, m, n, fc3_rec_elem)
#endif
for (jk = 0; jk < num_patom * num_patom; jk++)
{
j = jk / num_patom;
k = jk % num_patom;
real_to_reciprocal_elements(fc3_rec_elem,
q_vecs,
fc3,
is_compact_fc3,
svecs,
multi_dims,
multiplicity,
p2s_map,
s2p_map,
i, j, k);
for (l = 0; l < 3; l++)
{
for (m = 0; m < 3; m++)
{
for (n = 0; n < 3; n++)
{
fc3_reciprocal[(i * 3 + l) * num_band * num_band + (j * 3 + m) * num_band + k * 3 + n] =
phonoc_complex_prod(fc3_rec_elem[l * 9 + m * 3 + n], pre_phase_factor);
}
for (jk = 0; jk < num_patom * num_patom; jk++) {
j = jk / num_patom;
k = jk % num_patom;
real_to_reciprocal_elements(
fc3_rec_elem, q_vecs, fc3, is_compact_fc3, svecs, multi_dims,
multiplicity, p2s_map, s2p_map, i, j, k);
for (l = 0; l < 3; l++) {
for (m = 0; m < 3; m++) {
for (n = 0; n < 3; n++) {
fc3_reciprocal[(i * 3 + l) * num_band * num_band +
(j * 3 + m) * num_band + k * 3 + n] =
phonoc_complex_prod(fc3_rec_elem[l * 9 + m * 3 + n],
pre_phase_factor);
}
}
}
}
}
}
}
}
static void real_to_reciprocal_elements(lapack_complex_double *fc3_rec_elem,
const double q_vecs[3][3],
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s,
const long *s2p,
const long pi0,
const long pi1,
const long pi2)
{
long i, j, k, l;
long num_satom, adrs_shift, adrs_vec1, adrs_vec2;
lapack_complex_double phase_factor, phase_factor1, phase_factor2;
double fc3_rec_real[27], fc3_rec_imag[27];
static void real_to_reciprocal_elements(
lapack_complex_double *fc3_rec_elem, const double q_vecs[3][3],
const double *fc3, const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2], const long (*multiplicity)[2], const long *p2s,
const long *s2p, const long pi0, const long pi1, const long pi2) {
long i, j, k, l;
long num_satom, adrs_shift, adrs_vec1, adrs_vec2;
lapack_complex_double phase_factor, phase_factor1, phase_factor2;
double fc3_rec_real[27], fc3_rec_imag[27];
for (i = 0; i < 27; i++)
{
fc3_rec_real[i] = 0;
fc3_rec_imag[i] = 0;
}
num_satom = multi_dims[0];
if (is_compact_fc3)
{
i = pi0;
}
else
{
i = p2s[pi0];
}
for (j = 0; j < num_satom; j++)
{
if (s2p[j] != p2s[pi1])
{
continue;
for (i = 0; i < 27; i++) {
fc3_rec_real[i] = 0;
fc3_rec_imag[i] = 0;
}
adrs_vec1 = j * multi_dims[1] + pi0;
phase_factor1 = get_phase_factor(q_vecs,
1,
svecs,
multiplicity[adrs_vec1]);
for (k = 0; k < num_satom; k++)
{
if (s2p[k] != p2s[pi2])
{
continue;
}
adrs_vec2 = k * multi_dims[1] + pi0;
phase_factor2 = get_phase_factor(q_vecs,
2,
svecs,
multiplicity[adrs_vec2]);
adrs_shift = i * 27 * num_satom * num_satom + j * 27 * num_satom + k * 27;
phase_factor = phonoc_complex_prod(phase_factor1, phase_factor2);
for (l = 0; l < 27; l++)
{
fc3_rec_real[l] +=
lapack_complex_double_real(phase_factor) * fc3[adrs_shift + l];
fc3_rec_imag[l] +=
lapack_complex_double_imag(phase_factor) * fc3[adrs_shift + l];
}
}
}
num_satom = multi_dims[0];
for (i = 0; i < 27; i++)
{
fc3_rec_elem[i] =
lapack_make_complex_double(fc3_rec_real[i], fc3_rec_imag[i]);
}
if (is_compact_fc3) {
i = pi0;
} else {
i = p2s[pi0];
}
for (j = 0; j < num_satom; j++) {
if (s2p[j] != p2s[pi1]) {
continue;
}
adrs_vec1 = j * multi_dims[1] + pi0;
phase_factor1 =
get_phase_factor(q_vecs, 1, svecs, multiplicity[adrs_vec1]);
for (k = 0; k < num_satom; k++) {
if (s2p[k] != p2s[pi2]) {
continue;
}
adrs_vec2 = k * multi_dims[1] + pi0;
phase_factor2 =
get_phase_factor(q_vecs, 2, svecs, multiplicity[adrs_vec2]);
adrs_shift =
i * 27 * num_satom * num_satom + j * 27 * num_satom + k * 27;
phase_factor = phonoc_complex_prod(phase_factor1, phase_factor2);
for (l = 0; l < 27; l++) {
fc3_rec_real[l] += lapack_complex_double_real(phase_factor) *
fc3[adrs_shift + l];
fc3_rec_imag[l] += lapack_complex_double_imag(phase_factor) *
fc3[adrs_shift + l];
}
}
}
for (i = 0; i < 27; i++) {
fc3_rec_elem[i] =
lapack_make_complex_double(fc3_rec_real[i], fc3_rec_imag[i]);
}
}
static lapack_complex_double
get_pre_phase_factor(const long i_patom,
const double q_vecs[3][3],
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s_map)
{
long i, j, svecs_adrs;
double pre_phase, sum_real, sum_imag;
lapack_complex_double pre_phase_factor;
static lapack_complex_double get_pre_phase_factor(const long i_patom,
const double q_vecs[3][3],
const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s_map) {
long i, j, svecs_adrs;
double pre_phase, sum_real, sum_imag;
lapack_complex_double pre_phase_factor;
svecs_adrs = p2s_map[i_patom] * multi_dims[1];
sum_real = 0;
sum_imag = 0;
for (i = 0; i < multiplicity[svecs_adrs][0]; i++)
{
pre_phase = 0;
for (j = 0; j < 3; j++)
{
pre_phase += svecs[multiplicity[svecs_adrs][1] + i][j] *
(q_vecs[0][j] + q_vecs[1][j] + q_vecs[2][j]);
svecs_adrs = p2s_map[i_patom] * multi_dims[1];
sum_real = 0;
sum_imag = 0;
for (i = 0; i < multiplicity[svecs_adrs][0]; i++) {
pre_phase = 0;
for (j = 0; j < 3; j++) {
pre_phase += svecs[multiplicity[svecs_adrs][1] + i][j] *
(q_vecs[0][j] + q_vecs[1][j] + q_vecs[2][j]);
}
pre_phase *= M_2PI;
sum_real += cos(pre_phase);
sum_imag += sin(pre_phase);
}
pre_phase *= M_2PI;
sum_real += cos(pre_phase);
sum_imag += sin(pre_phase);
}
sum_real /= multiplicity[svecs_adrs][0];
sum_imag /= multiplicity[svecs_adrs][0];
pre_phase_factor = lapack_make_complex_double(sum_real, sum_imag);
return pre_phase_factor;
sum_real /= multiplicity[svecs_adrs][0];
sum_imag /= multiplicity[svecs_adrs][0];
pre_phase_factor = lapack_make_complex_double(sum_real, sum_imag);
return pre_phase_factor;
}
static lapack_complex_double get_phase_factor(const double q[3][3],
const long qi,
const double (*svecs)[3],
const long multi[2])
{
long i, j;
double sum_real, sum_imag, phase;
const long multi[2]) {
long i, j;
double sum_real, sum_imag, phase;
sum_real = 0;
sum_imag = 0;
for (i = 0; i < multi[0]; i++)
{
phase = 0;
for (j = 0; j < 3; j++)
{
phase += q[qi][j] * svecs[multi[1] + i][j];
sum_real = 0;
sum_imag = 0;
for (i = 0; i < multi[0]; i++) {
phase = 0;
for (j = 0; j < 3; j++) {
phase += q[qi][j] * svecs[multi[1] + i][j];
}
phase *= M_2PI;
sum_real += cos(phase);
sum_imag += sin(phase);
}
phase *= M_2PI;
sum_real += cos(phase);
sum_imag += sin(phase);
}
sum_real /= multi[0];
sum_imag /= multi[0];
sum_real /= multi[0];
sum_imag /= multi[0];
return lapack_make_complex_double(sum_real, sum_imag);
return lapack_make_complex_double(sum_real, sum_imag);
}

View File

@ -35,17 +35,13 @@
#ifndef __real_to_reciprocal_H__
#define __real_to_reciprocal_H__
#include "phonoc_array.h"
#include "lapack_wrapper.h"
#include "phonoc_array.h"
void r2r_real_to_reciprocal(lapack_complex_double *fc3_reciprocal,
const double q_vecs[3][3],
const double *fc3,
const long is_compact_fc3,
const double (*svecs)[3],
const double q_vecs[3][3], const double *fc3,
const long is_compact_fc3, const double (*svecs)[3],
const long multi_dims[2],
const long (*multiplicity)[2],
const long *p2s_map,
const long *s2p_map,
const long openmp_at_bands);
const long (*multiplicity)[2], const long *p2s_map,
const long *s2p_map, const long openmp_at_bands);
#endif

View File

@ -32,14 +32,16 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include <stdlib.h>
#include <math.h>
#include "reciprocal_to_normal.h"
#include <math.h>
#include <stdlib.h>
#include "lapack_wrapper.h"
#ifdef MEASURE_R2N
#include <unistd.h>
#include <time.h>
#include <unistd.h>
#endif
static double get_fc3_sum(const lapack_complex_double *e0,
@ -48,144 +50,125 @@ static double get_fc3_sum(const lapack_complex_double *e0,
const lapack_complex_double *fc3_reciprocal,
const long num_band);
void reciprocal_to_normal_squared(double *fc3_normal_squared,
const long (*g_pos)[4],
const long num_g_pos,
const lapack_complex_double *fc3_reciprocal,
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 double *masses,
const long *band_indices,
const long num_band,
const double cutoff_frequency,
const long openmp_at_bands)
{
long i, j, k, num_atom;
double real, imag;
double *inv_sqrt_masses;
lapack_complex_double *e0, *e1, *e2;
void reciprocal_to_normal_squared(
double *fc3_normal_squared, const long (*g_pos)[4], const long num_g_pos,
const lapack_complex_double *fc3_reciprocal, 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 double *masses,
const long *band_indices, const long num_band,
const double cutoff_frequency, const long openmp_at_bands) {
long i, j, k, num_atom;
double real, imag;
double *inv_sqrt_masses;
lapack_complex_double *e0, *e1, *e2;
/* Transpose eigenvectors for the better data alignment in memory. */
/* Memory space for three eigenvector matrices is allocated at once */
/* to make it contiguous. */
e0 = (lapack_complex_double *)
malloc(sizeof(lapack_complex_double) * 3 * num_band * num_band);
e1 = e0 + num_band * num_band;
e2 = e1 + num_band * num_band;
/* Transpose eigenvectors for the better data alignment in memory. */
/* Memory space for three eigenvector matrices is allocated at once */
/* to make it contiguous. */
e0 = (lapack_complex_double *)malloc(sizeof(lapack_complex_double) * 3 *
num_band * num_band);
e1 = e0 + num_band * num_band;
e2 = e1 + num_band * num_band;
for (i = 0; i < num_band; i++)
{
for (j = 0; j < num_band; j++)
{
e0[j * num_band + i] = eigvecs0[i * num_band + j];
e1[j * num_band + i] = eigvecs1[i * num_band + j];
e2[j * num_band + i] = eigvecs2[i * num_band + j];
for (i = 0; i < num_band; i++) {
for (j = 0; j < num_band; j++) {
e0[j * num_band + i] = eigvecs0[i * num_band + j];
e1[j * num_band + i] = eigvecs1[i * num_band + j];
e2[j * num_band + i] = eigvecs2[i * num_band + j];
}
}
}
/* Inverse sqrt mass is multipled with eigenvectors to reduce number of */
/* operations in get_fc3_sum. Three eigenvector matrices are looped by */
/* first loop leveraging contiguous memory layout of [e0, e1, e2]. */
num_atom = num_band / 3;
inv_sqrt_masses = (double *)malloc(sizeof(double) * num_atom);
for (i = 0; i < num_atom; i++)
{
inv_sqrt_masses[i] = 1.0 / sqrt(masses[i]);
}
for (i = 0; i < 3 * num_band; i++)
{
for (j = 0; j < num_atom; j++)
{
for (k = 0; k < 3; k++)
{
real = lapack_complex_double_real(e0[i * num_band + j * 3 + k]);
imag = lapack_complex_double_imag(e0[i * num_band + j * 3 + k]);
e0[i * num_band + j * 3 + k] = lapack_make_complex_double(real * inv_sqrt_masses[j], imag * inv_sqrt_masses[j]);
}
/* Inverse sqrt mass is multipled with eigenvectors to reduce number of */
/* operations in get_fc3_sum. Three eigenvector matrices are looped by */
/* first loop leveraging contiguous memory layout of [e0, e1, e2]. */
num_atom = num_band / 3;
inv_sqrt_masses = (double *)malloc(sizeof(double) * num_atom);
for (i = 0; i < num_atom; i++) {
inv_sqrt_masses[i] = 1.0 / sqrt(masses[i]);
}
}
free(inv_sqrt_masses);
inv_sqrt_masses = NULL;
for (i = 0; i < 3 * num_band; i++) {
for (j = 0; j < num_atom; j++) {
for (k = 0; k < 3; k++) {
real = lapack_complex_double_real(e0[i * num_band + j * 3 + k]);
imag = lapack_complex_double_imag(e0[i * num_band + j * 3 + k]);
e0[i * num_band + j * 3 + k] = lapack_make_complex_double(
real * inv_sqrt_masses[j], imag * inv_sqrt_masses[j]);
}
}
}
free(inv_sqrt_masses);
inv_sqrt_masses = NULL;
#ifdef MEASURE_R2N
double loopTotalCPUTime,
loopTotalWallTime;
time_t loopStartWallTime;
clock_t loopStartCPUTime;
double loopTotalCPUTime, loopTotalWallTime;
time_t loopStartWallTime;
clock_t loopStartCPUTime;
#endif
#ifdef MEASURE_R2N
loopStartWallTime = time(NULL);
loopStartCPUTime = clock();
loopStartWallTime = time(NULL);
loopStartCPUTime = clock();
#endif
#ifdef PHPYOPENMP
#pragma omp parallel for if (openmp_at_bands)
#endif
for (i = 0; i < num_g_pos; i++)
{
if (freqs0[band_indices[g_pos[i][0]]] > cutoff_frequency &&
freqs1[g_pos[i][1]] > cutoff_frequency &&
freqs2[g_pos[i][2]] > cutoff_frequency)
{
fc3_normal_squared[g_pos[i][3]] =
get_fc3_sum(e0 + band_indices[g_pos[i][0]] * num_band,
e1 + g_pos[i][1] * num_band,
e2 + g_pos[i][2] * num_band,
fc3_reciprocal,
num_band) /
(freqs0[band_indices[g_pos[i][0]]] * freqs1[g_pos[i][1]] * freqs2[g_pos[i][2]]);
for (i = 0; i < num_g_pos; i++) {
if (freqs0[band_indices[g_pos[i][0]]] > cutoff_frequency &&
freqs1[g_pos[i][1]] > cutoff_frequency &&
freqs2[g_pos[i][2]] > cutoff_frequency) {
fc3_normal_squared[g_pos[i][3]] =
get_fc3_sum(e0 + band_indices[g_pos[i][0]] * num_band,
e1 + g_pos[i][1] * num_band,
e2 + g_pos[i][2] * num_band, fc3_reciprocal,
num_band) /
(freqs0[band_indices[g_pos[i][0]]] * freqs1[g_pos[i][1]] *
freqs2[g_pos[i][2]]);
} else {
fc3_normal_squared[g_pos[i][3]] = 0;
}
}
else
{
fc3_normal_squared[g_pos[i][3]] = 0;
}
}
#ifdef MEASURE_R2N
loopTotalCPUTime = (double)(clock() - loopStartCPUTime) / CLOCKS_PER_SEC;
loopTotalWallTime = difftime(time(NULL), loopStartWallTime);
printf(" %1.3fs (%1.3fs CPU)\n", loopTotalWallTime, loopTotalCPUTime);
loopTotalCPUTime = (double)(clock() - loopStartCPUTime) / CLOCKS_PER_SEC;
loopTotalWallTime = difftime(time(NULL), loopStartWallTime);
printf(" %1.3fs (%1.3fs CPU)\n", loopTotalWallTime, loopTotalCPUTime);
#endif
free(e0);
e0 = NULL;
e1 = NULL;
e2 = NULL;
free(e0);
e0 = NULL;
e1 = NULL;
e2 = NULL;
}
static double get_fc3_sum(const lapack_complex_double *e0,
const lapack_complex_double *e1,
const lapack_complex_double *e2,
const lapack_complex_double *fc3_reciprocal,
const long num_band)
{
long i, j, k;
double sum_real, sum_imag;
lapack_complex_double e_01, e_012, e_012_fc3;
const long num_band) {
long i, j, k;
double sum_real, sum_imag;
lapack_complex_double e_01, e_012, e_012_fc3;
sum_real = 0;
sum_imag = 0;
sum_real = 0;
sum_imag = 0;
for (i = 0; i < num_band; i++)
{
for (j = 0; j < num_band; j++)
{
e_01 = phonoc_complex_prod(e0[i], e1[j]);
for (k = 0; k < num_band; k++)
{
e_012 = phonoc_complex_prod(e_01, e2[k]);
e_012_fc3 = phonoc_complex_prod(e_012, fc3_reciprocal[i * num_band * num_band + j * num_band + k]);
sum_real += lapack_complex_double_real(e_012_fc3);
sum_imag += lapack_complex_double_imag(e_012_fc3);
}
for (i = 0; i < num_band; i++) {
for (j = 0; j < num_band; j++) {
e_01 = phonoc_complex_prod(e0[i], e1[j]);
for (k = 0; k < num_band; k++) {
e_012 = phonoc_complex_prod(e_01, e2[k]);
e_012_fc3 = phonoc_complex_prod(
e_012,
fc3_reciprocal[i * num_band * num_band + j * num_band + k]);
sum_real += lapack_complex_double_real(e_012_fc3);
sum_imag += lapack_complex_double_imag(e_012_fc3);
}
}
}
}
return (sum_real * sum_real + sum_imag * sum_imag);
return (sum_real * sum_real + sum_imag * sum_imag);
}

View File

@ -37,20 +37,14 @@
#include "lapack_wrapper.h"
void reciprocal_to_normal_squared(double *fc3_normal_squared,
const long (*g_pos)[4],
const long num_g_pos,
const lapack_complex_double *fc3_reciprocal,
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 double *masses,
const long *band_indices,
const long num_band,
const double cutoff_frequency,
const long openmp_at_bands);
void reciprocal_to_normal_squared(
double *fc3_normal_squared, const long (*g_pos)[4], const long num_g_pos,
const lapack_complex_double *fc3_reciprocal, 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 double *masses,
const long *band_indices, const long num_band,
const double cutoff_frequency, const long openmp_at_bands);
#endif

View File

@ -20,21 +20,21 @@ static void zero_second_column(long L[3][3], SNF3x3CONST long A[3][3]);
static void second_finalize(long L[3][3], SNF3x3CONST long A[3][3]);
static void finalize(long A[3][3], long P[3][3], long Q[3][3]);
static void finalize_sort(long A[3][3], long P[3][3], long Q[3][3]);
static void finalize_disturb(long A[3][3], long Q[3][3], const int i, const int j);
static void finalize_disturb(long A[3][3], long Q[3][3], const int i,
const int j);
static void disturb_rows(long L[3][3], const int i, const int j);
static void swap_diag_elems(long A[3][3], long P[3][3], long Q[3][3], const int i, const int j);
static void swap_diag_elems(long A[3][3], long P[3][3], long Q[3][3],
const int i, const int j);
static void make_diagA_positive(long A[3][3], long P[3][3]);
static void flip_PQ(long P[3][3], long Q[3][3]);
static void swap_rows(long L[3][3], const int i, const int j);
static void set_zero(long L[3][3],
const int i, const int j, const long a, const long b,
const long r, const long s, const long t);
static void set_zero(long L[3][3], const int i, const int j, const long a,
const long b, const long r, const long s, const long t);
static void extended_gcd(long retvals[3], const long a, const long b);
static void extended_gcd_step(long vals[6]);
static void flip_sign_row(long L[3][3], const int i);
static void transpose(long m[3][3]);
static void matmul(long m[3][3],
SNF3x3CONST long a[3][3],
static void matmul(long m[3][3], SNF3x3CONST long a[3][3],
SNF3x3CONST long b[3][3]);
static long det(SNF3x3CONST long m[3][3]);
@ -51,487 +51,421 @@ static long det(SNF3x3CONST long m[3][3]);
* static void test_second_one_loop(void);
* static void test_second(void); */
int snf3x3(long A[3][3], long P[3][3], long Q[3][3])
{
int i;
initialize_PQ(P, Q);
int snf3x3(long A[3][3], long P[3][3], long Q[3][3]) {
int i;
initialize_PQ(P, Q);
for (i = 0; i < 100; i++)
{
if (first(A, P, Q))
{
if (second(A, P, Q))
{
finalize(A, P, Q);
transpose(Q);
goto succeeded;
}
for (i = 0; i < 100; i++) {
if (first(A, P, Q)) {
if (second(A, P, Q)) {
finalize(A, P, Q);
transpose(Q);
goto succeeded;
}
}
}
}
return 0;
return 0;
succeeded:
return 1;
return 1;
}
static void initialize_PQ(long P[3][3], long Q[3][3])
{
int i, j;
static void initialize_PQ(long P[3][3], long Q[3][3]) {
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
if (i == j)
{
P[i][j] = 1;
Q[i][j] = 1;
}
else
{
P[i][j] = 0;
Q[i][j] = 0;
}
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
if (i == j) {
P[i][j] = 1;
Q[i][j] = 1;
} else {
P[i][j] = 0;
Q[i][j] = 0;
}
}
}
}
}
static int first(long A[3][3], long P[3][3], long Q[3][3])
{
long L[3][3];
static int first(long A[3][3], long P[3][3], long Q[3][3]) {
long L[3][3];
first_one_loop(A, P, Q);
first_one_loop(A, P, Q);
/* rows and columns are all zero except for the pivot */
if ((A[1][0] == 0) && (A[2][0] == 0))
{
return 1;
}
/* rows and columns are all zero except for the pivot */
if ((A[1][0] == 0) && (A[2][0] == 0)) {
return 1;
}
/* columns of the pivot are assumed zero because of first_one_loop. */
/* rows of the pivot are non-zero, but divisible by the pivot. */
/* first_finalize makes the rows be zero. */
if ((A[1][0] % A[0][0] == 0) && (A[2][0] % A[0][0] == 0))
{
first_finalize(L, A);
matmul(A, L, A);
matmul(P, L, P);
return 1;
}
return 0;
/* columns of the pivot are assumed zero because of first_one_loop. */
/* rows of the pivot are non-zero, but divisible by the pivot. */
/* first_finalize makes the rows be zero. */
if ((A[1][0] % A[0][0] == 0) && (A[2][0] % A[0][0] == 0)) {
first_finalize(L, A);
matmul(A, L, A);
matmul(P, L, P);
return 1;
}
return 0;
}
static void first_one_loop(long A[3][3], long P[3][3], long Q[3][3])
{
first_column(A, P);
transpose(A);
first_column(A, Q);
transpose(A);
static void first_one_loop(long A[3][3], long P[3][3], long Q[3][3]) {
first_column(A, P);
transpose(A);
first_column(A, Q);
transpose(A);
}
static void first_column(long A[3][3], long P[3][3])
{
int i;
long L[3][3];
static void first_column(long A[3][3], long P[3][3]) {
int i;
long L[3][3];
i = search_first_pivot(A);
if (i > 0)
{
swap_rows(L, 0, i);
matmul(A, L, A);
matmul(P, L, P);
}
if (i < 0)
{
goto err;
}
i = search_first_pivot(A);
if (i > 0) {
swap_rows(L, 0, i);
matmul(A, L, A);
matmul(P, L, P);
}
if (i < 0) {
goto err;
}
if (A[1][0] != 0)
{
zero_first_column(L, 1, A);
matmul(A, L, A);
matmul(P, L, P);
}
if (A[2][0] != 0)
{
zero_first_column(L, 2, A);
matmul(A, L, A);
matmul(P, L, P);
}
if (A[1][0] != 0) {
zero_first_column(L, 1, A);
matmul(A, L, A);
matmul(P, L, P);
}
if (A[2][0] != 0) {
zero_first_column(L, 2, A);
matmul(A, L, A);
matmul(P, L, P);
}
err:;
}
static void zero_first_column(long L[3][3], const int j,
SNF3x3CONST long A[3][3])
{
long vals[3];
SNF3x3CONST long A[3][3]) {
long vals[3];
extended_gcd(vals, A[0][0], A[j][0]);
set_zero(L, 0, j, A[0][0], A[j][0], vals[0], vals[1], vals[2]);
extended_gcd(vals, A[0][0], A[j][0]);
set_zero(L, 0, j, A[0][0], A[j][0], vals[0], vals[1], vals[2]);
}
static int search_first_pivot(SNF3x3CONST long A[3][3])
{
int i;
static int search_first_pivot(SNF3x3CONST long A[3][3]) {
int i;
for (i = 0; i < 3; i++)
{
if (A[i][0] != 0)
{
return i;
for (i = 0; i < 3; i++) {
if (A[i][0] != 0) {
return i;
}
}
}
return -1;
return -1;
}
static void first_finalize(long L[3][3], SNF3x3CONST long A[3][3])
{
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = -A[1][0] / A[0][0];
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = -A[2][0] / A[0][0];
L[2][1] = 0;
L[2][2] = 1;
static void first_finalize(long L[3][3], SNF3x3CONST long A[3][3]) {
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = -A[1][0] / A[0][0];
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = -A[2][0] / A[0][0];
L[2][1] = 0;
L[2][2] = 1;
}
static int second(long A[3][3], long P[3][3], long Q[3][3])
{
long L[3][3];
static int second(long A[3][3], long P[3][3], long Q[3][3]) {
long L[3][3];
second_one_loop(A, P, Q);
second_one_loop(A, P, Q);
if (A[2][1] == 0)
{
return 1;
}
if (A[2][1] == 0) {
return 1;
}
if (A[2][1] % A[1][1] == 0)
{
second_finalize(L, A);
matmul(A, L, A);
matmul(P, L, P);
return 1;
}
if (A[2][1] % A[1][1] == 0) {
second_finalize(L, A);
matmul(A, L, A);
matmul(P, L, P);
return 1;
}
return 0;
return 0;
}
static void second_one_loop(long A[3][3], long P[3][3], long Q[3][3])
{
second_column(A, P);
transpose(A);
second_column(A, Q);
transpose(A);
}
static void second_column(long A[3][3], long P[3][3])
{
long L[3][3];
if ((A[1][1] == 0) && (A[2][1] != 0))
{
swap_rows(L, 1, 2);
matmul(A, L, A);
matmul(P, L, P);
}
if (A[2][1] != 0)
{
zero_second_column(L, A);
matmul(A, L, A);
matmul(P, L, P);
}
}
static void zero_second_column(long L[3][3], SNF3x3CONST long A[3][3])
{
long vals[3];
extended_gcd(vals, A[1][1], A[2][1]);
set_zero(L, 1, 2, A[1][1], A[2][1], vals[0], vals[1], vals[2]);
}
static void second_finalize(long L[3][3], SNF3x3CONST long A[3][3])
{
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = 0;
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = 0;
L[2][1] = -A[2][1] / A[1][1];
L[2][2] = 1;
}
static void finalize(long A[3][3], long P[3][3], long Q[3][3])
{
make_diagA_positive(A, P);
finalize_sort(A, P, Q);
finalize_disturb(A, Q, 0, 1);
first(A, P, Q);
finalize_sort(A, P, Q);
finalize_disturb(A, Q, 1, 2);
second(A, P, Q);
flip_PQ(P, Q);
}
static void finalize_sort(long A[3][3], long P[3][3], long Q[3][3])
{
if (A[0][0] > A[1][1])
{
swap_diag_elems(A, P, Q, 0, 1);
}
if (A[1][1] > A[2][2])
{
swap_diag_elems(A, P, Q, 1, 2);
}
if (A[0][0] > A[1][1])
{
swap_diag_elems(A, P, Q, 0, 1);
}
}
static void finalize_disturb(long A[3][3], long Q[3][3], const int i, const int j)
{
long L[3][3];
if (A[j][j] % A[i][i] != 0)
{
static void second_one_loop(long A[3][3], long P[3][3], long Q[3][3]) {
second_column(A, P);
transpose(A);
disturb_rows(L, i, j);
second_column(A, Q);
transpose(A);
}
static void second_column(long A[3][3], long P[3][3]) {
long L[3][3];
if ((A[1][1] == 0) && (A[2][1] != 0)) {
swap_rows(L, 1, 2);
matmul(A, L, A);
matmul(P, L, P);
}
if (A[2][1] != 0) {
zero_second_column(L, A);
matmul(A, L, A);
matmul(P, L, P);
}
}
static void zero_second_column(long L[3][3], SNF3x3CONST long A[3][3]) {
long vals[3];
extended_gcd(vals, A[1][1], A[2][1]);
set_zero(L, 1, 2, A[1][1], A[2][1], vals[0], vals[1], vals[2]);
}
static void second_finalize(long L[3][3], SNF3x3CONST long A[3][3]) {
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = 0;
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = 0;
L[2][1] = -A[2][1] / A[1][1];
L[2][2] = 1;
}
static void finalize(long A[3][3], long P[3][3], long Q[3][3]) {
make_diagA_positive(A, P);
finalize_sort(A, P, Q);
finalize_disturb(A, Q, 0, 1);
first(A, P, Q);
finalize_sort(A, P, Q);
finalize_disturb(A, Q, 1, 2);
second(A, P, Q);
flip_PQ(P, Q);
}
static void finalize_sort(long A[3][3], long P[3][3], long Q[3][3]) {
if (A[0][0] > A[1][1]) {
swap_diag_elems(A, P, Q, 0, 1);
}
if (A[1][1] > A[2][2]) {
swap_diag_elems(A, P, Q, 1, 2);
}
if (A[0][0] > A[1][1]) {
swap_diag_elems(A, P, Q, 0, 1);
}
}
static void finalize_disturb(long A[3][3], long Q[3][3], const int i,
const int j) {
long L[3][3];
if (A[j][j] % A[i][i] != 0) {
transpose(A);
disturb_rows(L, i, j);
matmul(A, L, A);
matmul(Q, L, Q);
transpose(A);
}
}
static void disturb_rows(long L[3][3], const int i, const int j) {
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = 0;
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = 0;
L[2][1] = 0;
L[2][2] = 1;
L[i][i] = 1;
L[i][j] = 1;
L[j][i] = 0;
L[j][j] = 1;
}
static void swap_diag_elems(long A[3][3], long P[3][3], long Q[3][3],
const int i, const int j) {
long L[3][3];
swap_rows(L, i, j);
matmul(A, L, A);
matmul(P, L, P);
transpose(A);
swap_rows(L, i, j);
matmul(A, L, A);
matmul(Q, L, Q);
transpose(A);
}
}
static void disturb_rows(long L[3][3], const int i, const int j)
{
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = 0;
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = 0;
L[2][1] = 0;
L[2][2] = 1;
L[i][i] = 1;
L[i][j] = 1;
L[j][i] = 0;
L[j][j] = 1;
}
static void make_diagA_positive(long A[3][3], long P[3][3]) {
int i;
long L[3][3];
static void swap_diag_elems(long A[3][3], long P[3][3], long Q[3][3], const int i, const int j)
{
long L[3][3];
swap_rows(L, i, j);
matmul(A, L, A);
matmul(P, L, P);
transpose(A);
swap_rows(L, i, j);
matmul(A, L, A);
matmul(Q, L, Q);
transpose(A);
}
static void make_diagA_positive(long A[3][3], long P[3][3])
{
int i;
long L[3][3];
for (i = 0; i < 3; i++)
{
if (A[i][i] < 0)
{
flip_sign_row(L, i);
matmul(A, L, A);
matmul(P, L, P);
for (i = 0; i < 3; i++) {
if (A[i][i] < 0) {
flip_sign_row(L, i);
matmul(A, L, A);
matmul(P, L, P);
}
}
}
}
static void flip_PQ(long P[3][3], long Q[3][3])
{
int i, j;
static void flip_PQ(long P[3][3], long Q[3][3]) {
int i, j;
if (det(P) < 0)
{
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
P[i][j] *= -1;
Q[i][j] *= -1;
}
if (det(P) < 0) {
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
P[i][j] *= -1;
Q[i][j] *= -1;
}
}
}
}
}
static void swap_rows(long L[3][3], const int r1, const int r2)
{
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = 0;
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = 0;
L[2][1] = 0;
L[2][2] = 1;
L[r1][r1] = 0;
L[r2][r2] = 0;
L[r1][r2] = 1;
L[r2][r1] = 1;
static void swap_rows(long L[3][3], const int r1, const int r2) {
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = 0;
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = 0;
L[2][1] = 0;
L[2][2] = 1;
L[r1][r1] = 0;
L[r2][r2] = 0;
L[r1][r2] = 1;
L[r2][r1] = 1;
}
static void set_zero(long L[3][3],
const int i, const int j, const long a, const long b,
const long r, const long s, const long t)
{
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = 0;
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = 0;
L[2][1] = 0;
L[2][2] = 1;
L[i][i] = s;
L[i][j] = t;
L[j][i] = -b / r;
L[j][j] = a / r;
static void set_zero(long L[3][3], const int i, const int j, const long a,
const long b, const long r, const long s, const long t) {
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = 0;
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = 0;
L[2][1] = 0;
L[2][2] = 1;
L[i][i] = s;
L[i][j] = t;
L[j][i] = -b / r;
L[j][j] = a / r;
}
/**
* Extended Euclidean algorithm
* See https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
*/
static void extended_gcd(long retvals[3], const long a, const long b)
{
int i;
long vals[6];
static void extended_gcd(long retvals[3], const long a, const long b) {
int i;
long vals[6];
vals[0] = a; /* r0 */
vals[1] = b; /* r1 */
vals[2] = 1; /* s0 */
vals[3] = 0; /* s1 */
vals[4] = 0; /* t0 */
vals[5] = 1; /* t1 */
vals[0] = a; /* r0 */
vals[1] = b; /* r1 */
vals[2] = 1; /* s0 */
vals[3] = 0; /* s1 */
vals[4] = 0; /* t0 */
vals[5] = 1; /* t1 */
for (i = 0; i < 1000; i++)
{
extended_gcd_step(vals);
if (vals[1] == 0)
{
break;
for (i = 0; i < 1000; i++) {
extended_gcd_step(vals);
if (vals[1] == 0) {
break;
}
}
}
retvals[0] = vals[0];
retvals[1] = vals[2];
retvals[2] = vals[4];
retvals[0] = vals[0];
retvals[1] = vals[2];
retvals[2] = vals[4];
assert(vals[0] == a * vals[2] + b * vals[4]);
assert(vals[0] == a * vals[2] + b * vals[4]);
}
static void extended_gcd_step(long vals[6])
{
long q, r2, s2, t2;
static void extended_gcd_step(long vals[6]) {
long q, r2, s2, t2;
q = vals[0] / vals[1];
r2 = vals[0] % vals[1];
if (r2 < 0)
{
if (vals[1] > 0)
{
r2 += vals[1];
q -= 1;
q = vals[0] / vals[1];
r2 = vals[0] % vals[1];
if (r2 < 0) {
if (vals[1] > 0) {
r2 += vals[1];
q -= 1;
}
if (vals[1] < 0) {
r2 -= vals[1];
q += 1;
}
}
if (vals[1] < 0)
{
r2 -= vals[1];
q += 1;
}
}
s2 = vals[2] - q * vals[3];
t2 = vals[4] - q * vals[5];
vals[0] = vals[1];
vals[1] = r2;
vals[2] = vals[3];
vals[3] = s2;
vals[4] = vals[5];
vals[5] = t2;
s2 = vals[2] - q * vals[3];
t2 = vals[4] - q * vals[5];
vals[0] = vals[1];
vals[1] = r2;
vals[2] = vals[3];
vals[3] = s2;
vals[4] = vals[5];
vals[5] = t2;
}
static void flip_sign_row(long L[3][3], const int i)
{
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = 0;
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = 0;
L[2][1] = 0;
L[2][2] = 1;
L[i][i] = -1;
static void flip_sign_row(long L[3][3], const int i) {
L[0][0] = 1;
L[0][1] = 0;
L[0][2] = 0;
L[1][0] = 0;
L[1][1] = 1;
L[1][2] = 0;
L[2][0] = 0;
L[2][1] = 0;
L[2][2] = 1;
L[i][i] = -1;
}
/**
* Matrix operation utils
*/
static void transpose(long m[3][3])
{
long tmp;
int i, j;
static void transpose(long m[3][3]) {
long tmp;
int i, j;
for (i = 0; i < 3; i++)
{
for (j = i; j < 3; j++)
{
tmp = m[i][j];
m[i][j] = m[j][i];
m[j][i] = tmp;
for (i = 0; i < 3; i++) {
for (j = i; j < 3; j++) {
tmp = m[i][j];
m[i][j] = m[j][i];
m[j][i] = tmp;
}
}
}
}
static void matmul(long m[3][3],
SNF3x3CONST long a[3][3],
SNF3x3CONST long b[3][3])
{
int i, j;
long c[3][3];
static void matmul(long m[3][3], SNF3x3CONST long a[3][3],
SNF3x3CONST long b[3][3]) {
int i, j;
long c[3][3];
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j];
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j];
}
}
}
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
m[i][j] = c[i][j];
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
m[i][j] = c[i][j];
}
}
}
}
static long det(SNF3x3CONST long m[3][3])
{
return m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) + m[0][1] * (m[1][2] * m[2][0] - m[1][0] * m[2][2]) + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
static long det(SNF3x3CONST long m[3][3]) {
return m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) +
m[0][1] * (m[1][2] * m[2][0] - m[1][0] * m[2][2]) +
m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
}
/* int main()

View File

@ -9,7 +9,7 @@ extern "C" {
#define SNF3X3_MINOR_VERSION 1
#define SNF3X3_MICRO_VERSION 0
int snf3x3(long A[3][3], long P[3][3], long Q[3][3]);
int snf3x3(long A[3][3], long P[3][3], long Q[3][3]);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@ -34,181 +34,121 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include "bzgrid.h"
#include "triplet.h"
#include "triplet_iw.h"
#include "bzgrid.h"
#include "triplet_grid.h"
#include "triplet_iw.h"
long tpl_get_BZ_triplets_at_q(long (*triplets)[3],
const long grid_point,
long tpl_get_BZ_triplets_at_q(long (*triplets)[3], const long grid_point,
const ConstBZGrid *bzgrid,
const long *map_triplets)
{
return tpk_get_BZ_triplets_at_q(triplets,
grid_point,
bzgrid,
map_triplets);
const long *map_triplets) {
return tpk_get_BZ_triplets_at_q(triplets, grid_point, bzgrid, map_triplets);
}
long tpl_get_triplets_reciprocal_mesh_at_q(long *map_triplets,
long *map_q,
const long grid_point,
const long mesh[3],
const long is_time_reversal,
const long num_rot,
const long (*rec_rotations)[3][3],
const long swappable)
{
long num_ir;
long tpl_get_triplets_reciprocal_mesh_at_q(
long *map_triplets, long *map_q, const long grid_point, const long mesh[3],
const long is_time_reversal, const long num_rot,
const long (*rec_rotations)[3][3], const long swappable) {
long num_ir;
num_ir = tpk_get_ir_triplets_at_q(map_triplets,
map_q,
grid_point,
mesh,
is_time_reversal,
rec_rotations,
num_rot,
swappable);
return num_ir;
num_ir = tpk_get_ir_triplets_at_q(map_triplets, map_q, grid_point, mesh,
is_time_reversal, rec_rotations, num_rot,
swappable);
return num_ir;
}
void tpl_get_integration_weight(double *iw,
char *iw_zero,
const double *frequency_points,
const long num_band0,
const long relative_grid_address[24][4][3],
const long (*triplets)[3],
const long num_triplets,
const ConstBZGrid *bzgrid,
const double *frequencies1,
const long num_band1,
const double *frequencies2,
const long num_band2,
const long tp_type,
const long openmp_per_triplets,
const long openmp_per_bands)
{
long i, num_band_prod;
long tp_relative_grid_address[2][24][4][3];
void tpl_get_integration_weight(
double *iw, char *iw_zero, const double *frequency_points,
const long num_band0, const long relative_grid_address[24][4][3],
const long (*triplets)[3], const long num_triplets,
const ConstBZGrid *bzgrid, const double *frequencies1, const long num_band1,
const double *frequencies2, const long num_band2, const long tp_type,
const long openmp_per_triplets, const long openmp_per_bands) {
long i, num_band_prod;
long tp_relative_grid_address[2][24][4][3];
tpl_set_relative_grid_address(tp_relative_grid_address,
relative_grid_address,
tp_type);
num_band_prod = num_band0 * num_band1 * num_band2;
tpl_set_relative_grid_address(tp_relative_grid_address,
relative_grid_address, tp_type);
num_band_prod = num_band0 * num_band1 * num_band2;
#ifdef PHPYOPENMP
#pragma omp parallel for if (openmp_per_triplets)
#endif
for (i = 0; i < num_triplets; i++)
{
tpi_get_integration_weight(iw + i * num_band_prod,
iw_zero + i * num_band_prod,
frequency_points, /* f0 */
num_band0,
tp_relative_grid_address,
triplets[i],
num_triplets,
bzgrid,
frequencies1, /* f1 */
num_band1,
frequencies2, /* f2 */
num_band2,
tp_type,
openmp_per_bands);
}
for (i = 0; i < num_triplets; i++) {
tpi_get_integration_weight(
iw + i * num_band_prod, iw_zero + i * num_band_prod,
frequency_points, /* f0 */
num_band0, tp_relative_grid_address, triplets[i], num_triplets,
bzgrid, frequencies1, /* f1 */
num_band1, frequencies2, /* f2 */
num_band2, tp_type, openmp_per_bands);
}
}
void tpl_get_integration_weight_with_sigma(double *iw,
char *iw_zero,
const double sigma,
const double sigma_cutoff,
const double *frequency_points,
const long num_band0,
const long (*triplets)[3],
const long num_triplets,
const double *frequencies,
const long num_band,
const long tp_type)
{
long i, num_band_prod, const_adrs_shift;
double cutoff;
void tpl_get_integration_weight_with_sigma(
double *iw, char *iw_zero, const double sigma, const double sigma_cutoff,
const double *frequency_points, const long num_band0,
const long (*triplets)[3], const long num_triplets,
const double *frequencies, const long num_band, const long tp_type) {
long i, num_band_prod, const_adrs_shift;
double cutoff;
cutoff = sigma * sigma_cutoff;
num_band_prod = num_band0 * num_band * num_band;
const_adrs_shift = num_triplets * num_band0 * num_band * num_band;
cutoff = sigma * sigma_cutoff;
num_band_prod = num_band0 * num_band * num_band;
const_adrs_shift = num_triplets * num_band0 * num_band * num_band;
#ifdef PHPYOPENMP
#pragma omp parallel for
#endif
for (i = 0; i < num_triplets; i++)
{
tpi_get_integration_weight_with_sigma(
iw + i * num_band_prod,
iw_zero + i * num_band_prod,
sigma,
cutoff,
frequency_points,
num_band0,
triplets[i],
const_adrs_shift,
frequencies,
num_band,
tp_type,
0);
}
for (i = 0; i < num_triplets; i++) {
tpi_get_integration_weight_with_sigma(
iw + i * num_band_prod, iw_zero + i * num_band_prod, sigma, cutoff,
frequency_points, num_band0, triplets[i], const_adrs_shift,
frequencies, num_band, tp_type, 0);
}
}
long tpl_is_N(const long triplet[3], const long (*bz_grid_addresses)[3])
{
long i, j, sum_q, is_N;
long tpl_is_N(const long triplet[3], const long (*bz_grid_addresses)[3]) {
long i, j, sum_q, is_N;
is_N = 1;
for (i = 0; i < 3; i++)
{
sum_q = 0;
for (j = 0; j < 3; j++)
{ /* 1st, 2nd, 3rd triplet */
sum_q += bz_grid_addresses[triplet[j]][i];
}
if (sum_q)
{
is_N = 0;
break;
}
}
return is_N;
}
void tpl_set_relative_grid_address(
long tp_relative_grid_address[2][24][4][3],
const long relative_grid_address[24][4][3],
const long tp_type)
{
long i, j, k, l;
long signs[2];
signs[0] = 1;
signs[1] = 1;
if ((tp_type == 2) || (tp_type == 3))
{
/* q1+q2+q3=G */
/* To set q2+1, q3-1 is needed to keep G */
signs[1] = -1;
}
/* tp_type == 4, q+k_i-k_f=G */
for (i = 0; i < 2; i++)
{
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] * signs[i];
is_N = 1;
for (i = 0; i < 3; i++) {
sum_q = 0;
for (j = 0; j < 3; j++) { /* 1st, 2nd, 3rd triplet */
sum_q += bz_grid_addresses[triplet[j]][i];
}
if (sum_q) {
is_N = 0;
break;
}
}
return is_N;
}
void tpl_set_relative_grid_address(long tp_relative_grid_address[2][24][4][3],
const long relative_grid_address[24][4][3],
const long tp_type) {
long i, j, k, l;
long signs[2];
signs[0] = 1;
signs[1] = 1;
if ((tp_type == 2) || (tp_type == 3)) {
/* q1+q2+q3=G */
/* To set q2+1, q3-1 is needed to keep G */
signs[1] = -1;
}
/* tp_type == 4, q+k_i-k_f=G */
for (i = 0; i < 2; i++) {
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] * signs[i];
}
}
}
}
}
}
}

View File

@ -38,6 +38,7 @@
#define __triplet_H__
#include <stddef.h>
#include "bzgrid.h"
/* Irreducible triplets of k-points are searched under conservation of */
@ -46,55 +47,35 @@
/* and map_q[prod(mesh)] are required. rotations are point-group- */
/* operations in real space for which duplicate operations are allowed */
/* in the input. */
long tpl_get_triplets_reciprocal_mesh_at_q(long *map_triplets,
long *map_q,
const long grid_point,
const long mesh[3],
const long is_time_reversal,
const long num_rot,
const long (*rec_rotations)[3][3],
const long swappable);
long tpl_get_triplets_reciprocal_mesh_at_q(
long *map_triplets, long *map_q, const long grid_point, const long mesh[3],
const long is_time_reversal, const long num_rot,
const long (*rec_rotations)[3][3], const long swappable);
/* Irreducible grid-point-triplets in BZ are stored. */
/* triplets are recovered from grid_point and triplet_weights. */
/* BZ boundary is considered in this recovery. Therefore grid addresses */
/* are given not by grid_address, but by bz_grid_address. */
/* triplets[num_ir_triplets][3] = number of non-zero triplets weights*/
/* Number of ir-triplets is returned. */
long tpl_get_BZ_triplets_at_q(long (*triplets)[3],
const long grid_point,
long tpl_get_BZ_triplets_at_q(long (*triplets)[3], const long grid_point,
const ConstBZGrid *bzgrid,
const long *map_triplets);
void tpl_get_integration_weight(double *iw,
char *iw_zero,
const double *frequency_points,
const long num_band0,
const long relative_grid_address[24][4][3],
const long (*triplets)[3],
const long num_triplets,
const ConstBZGrid *bzgrid,
const double *frequencies1,
const long num_band1,
const double *frequencies2,
const long num_band2,
const long tp_type,
const long openmp_per_triplets,
const long openmp_per_bands);
void tpl_get_integration_weight_with_sigma(double *iw,
char *iw_zero,
const double sigma,
const double sigma_cutoff,
const double *frequency_points,
const long num_band0,
const long (*triplets)[3],
const long num_triplets,
const double *frequencies,
const long num_band,
const long tp_type);
void tpl_get_integration_weight(
double *iw, char *iw_zero, const double *frequency_points,
const long num_band0, const long relative_grid_address[24][4][3],
const long (*triplets)[3], const long num_triplets,
const ConstBZGrid *bzgrid, const double *frequencies1, const long num_band1,
const double *frequencies2, const long num_band2, const long tp_type,
const long openmp_per_triplets, const long openmp_per_bands);
void tpl_get_integration_weight_with_sigma(
double *iw, char *iw_zero, const double sigma, const double sigma_cutoff,
const double *frequency_points, const long num_band0,
const long (*triplets)[3], const long num_triplets,
const double *frequencies, const long num_band, const long tp_type);
long tpl_is_N(const long triplet[3], const long (*bz_grid_addresses)[3]);
void tpl_set_relative_grid_address(
long tp_relative_grid_address[2][24][4][3],
const long relative_grid_address[24][4][3],
const long tp_type);
void tpl_set_relative_grid_address(long tp_relative_grid_address[2][24][4][3],
const long relative_grid_address[24][4][3],
const long tp_type);
#endif

View File

@ -34,33 +34,28 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include "triplet_grid.h"
#include <stddef.h>
#include <stdlib.h>
#include "bzgrid.h"
#include "grgrid.h"
#include "lagrid.h"
#include "triplet.h"
#include "triplet_grid.h"
static long get_ir_triplets_at_q(long *map_triplets,
long *map_q,
const long grid_point,
const long D_diag[3],
static long get_ir_triplets_at_q(long *map_triplets, long *map_q,
const long grid_point, const long D_diag[3],
const RotMats *rot_reciprocal,
const long swappable);
static long get_ir_triplets_at_q_perm_q1q2(long *map_triplets,
const long *map_q,
const long grid_point,
const long D_diag[3],
const RotMats *rot_reciprocal_q,
const long num_ir_q);
static long get_ir_triplets_at_q_noperm(long *map_triplets,
const long *map_q,
const long D_diag[3]);
static long get_ir_triplets_at_q_noperm(long *map_triplets, const long *map_q,
const long grid_point,
const long D_diag[3],
const RotMats *rot_reciprocal_q);
static long get_BZ_triplets_at_q(long (*triplets)[3],
const long grid_point,
const long D_diag[3]);
static long get_BZ_triplets_at_q(long (*triplets)[3], const long grid_point,
const ConstBZGrid *bzgrid,
const long *map_triplets);
static void get_BZ_triplets_at_q_type1(long (*triplets)[3],
@ -73,8 +68,7 @@ static void get_BZ_triplets_at_q_type2(long (*triplets)[3],
const ConstBZGrid *bzgrid,
const long *ir_q1_gps,
const long num_ir);
static double get_squared_distance(const long G[3],
const double LQD_inv[3][3]);
static double get_squared_distance(const long G[3], const double LQD_inv[3][3]);
static void get_LQD_inv(double LQD_inv[3][3], const ConstBZGrid *bzgrid);
static RotMats *get_reciprocal_point_group_with_q(const RotMats *rot_reciprocal,
const long D_diag[3],
@ -84,569 +78,424 @@ static RotMats *get_reciprocal_point_group(const long (*rec_rotations_in)[3][3],
const long is_time_reversal,
const long is_transpose);
long tpk_get_ir_triplets_at_q(long *map_triplets,
long *map_q,
const long grid_point,
const long D_diag[3],
long tpk_get_ir_triplets_at_q(long *map_triplets, long *map_q,
const long grid_point, const long D_diag[3],
const long is_time_reversal,
const long (*rec_rotations_in)[3][3],
const long num_rot,
const long swappable)
{
long num_ir;
RotMats *rotations;
const long num_rot, const long swappable) {
long num_ir;
RotMats *rotations;
rotations = get_reciprocal_point_group(rec_rotations_in,
num_rot,
is_time_reversal,
0);
if (rotations == NULL)
{
return 0;
}
num_ir = get_ir_triplets_at_q(map_triplets,
map_q,
grid_point,
D_diag,
rotations,
swappable);
bzg_free_RotMats(rotations);
rotations = NULL;
return num_ir;
}
long tpk_get_BZ_triplets_at_q(long (*triplets)[3],
const long grid_point,
const ConstBZGrid *bzgrid,
const long *map_triplets)
{
return get_BZ_triplets_at_q(triplets,
grid_point,
bzgrid,
map_triplets);
}
static long get_ir_triplets_at_q(long *map_triplets,
long *map_q,
const long grid_point,
const long D_diag[3],
const RotMats *rot_reciprocal,
const long swappable)
{
long i, num_ir_q, num_ir_triplets;
long PS[3];
RotMats *rot_reciprocal_q;
rot_reciprocal_q = NULL;
for (i = 0; i < 3; i++)
{
PS[i] = 0;
}
/* Search irreducible q-points (map_q) with a stabilizer. */
rot_reciprocal_q = get_reciprocal_point_group_with_q(rot_reciprocal,
D_diag,
grid_point);
grg_get_ir_grid_map(map_q,
rot_reciprocal_q->mat,
rot_reciprocal_q->size,
D_diag,
PS);
num_ir_q = 0;
for (i = 0; i < D_diag[0] * D_diag[1] * D_diag[2]; i++)
{
if (map_q[i] == i)
{
num_ir_q++;
rotations = get_reciprocal_point_group(rec_rotations_in, num_rot,
is_time_reversal, 0);
if (rotations == NULL) {
return 0;
}
}
if (swappable)
{
num_ir_triplets = get_ir_triplets_at_q_perm_q1q2(map_triplets,
map_q,
grid_point,
D_diag,
rot_reciprocal_q,
num_ir_q);
}
else
{
num_ir_triplets = get_ir_triplets_at_q_noperm(map_triplets,
map_q,
grid_point,
D_diag,
rot_reciprocal_q);
}
num_ir = get_ir_triplets_at_q(map_triplets, map_q, grid_point, D_diag,
rotations, swappable);
bzg_free_RotMats(rotations);
rotations = NULL;
bzg_free_RotMats(rot_reciprocal_q);
rot_reciprocal_q = NULL;
return num_ir;
}
return num_ir_triplets;
long tpk_get_BZ_triplets_at_q(long (*triplets)[3], const long grid_point,
const ConstBZGrid *bzgrid,
const long *map_triplets) {
return get_BZ_triplets_at_q(triplets, grid_point, bzgrid, map_triplets);
}
static long get_ir_triplets_at_q(long *map_triplets, long *map_q,
const long grid_point, const long D_diag[3],
const RotMats *rot_reciprocal,
const long swappable) {
long i, num_ir_q, num_ir_triplets;
long PS[3];
RotMats *rot_reciprocal_q;
rot_reciprocal_q = NULL;
for (i = 0; i < 3; i++) {
PS[i] = 0;
}
/* Search irreducible q-points (map_q) with a stabilizer. */
rot_reciprocal_q =
get_reciprocal_point_group_with_q(rot_reciprocal, D_diag, grid_point);
grg_get_ir_grid_map(map_q, rot_reciprocal_q->mat, rot_reciprocal_q->size,
D_diag, PS);
num_ir_q = 0;
for (i = 0; i < D_diag[0] * D_diag[1] * D_diag[2]; i++) {
if (map_q[i] == i) {
num_ir_q++;
}
}
if (swappable) {
num_ir_triplets = get_ir_triplets_at_q_perm_q1q2(map_triplets, map_q,
grid_point, D_diag);
} else {
num_ir_triplets = get_ir_triplets_at_q_noperm(map_triplets, map_q,
grid_point, D_diag);
}
bzg_free_RotMats(rot_reciprocal_q);
rot_reciprocal_q = NULL;
return num_ir_triplets;
}
static long get_ir_triplets_at_q_perm_q1q2(long *map_triplets,
const long *map_q,
const long grid_point,
const long D_diag[3],
const RotMats *rot_reciprocal_q,
const long num_ir_q)
{
long i, j, num_grid, num_ir_triplets, ir_gp, count;
long adrs0[3], adrs1[3], adrs2[3];
long *ir_gps_at_q, *q_2;
const long D_diag[3]) {
long j, num_grid, num_ir_triplets, gp1, gp2;
long adrs0[3], adrs1[3], adrs2[3];
ir_gps_at_q = NULL;
q_2 = NULL;
num_ir_triplets = 0;
num_ir_triplets = 0;
num_grid = D_diag[0] * D_diag[1] * D_diag[2];
grg_get_grid_address_from_index(adrs0, grid_point, D_diag);
num_grid = D_diag[0] * D_diag[1] * D_diag[2];
if ((q_2 = (long *)malloc(sizeof(long) * num_ir_q)) == NULL)
{
warning_print("Memory could not be allocated.");
goto ret;
}
if ((ir_gps_at_q = (long *)malloc(sizeof(long) * num_ir_q)) == NULL)
{
warning_print("Memory could not be allocated.");
goto ret;
}
count = 0;
for (i = 0; i < num_grid; i++)
{
if (map_q[i] == i)
{
ir_gps_at_q[count] = i;
count++;
// #ifdef PHPYOPENMP
// #pragma omp parallel for private(j, gp2, adrs1, adrs2)
// #endif
for (gp1 = 0; gp1 < num_grid; gp1++) {
if (map_q[gp1] == gp1) {
grg_get_grid_address_from_index(adrs1, gp1, D_diag);
for (j = 0; j < 3; j++) {
adrs2[j] = -adrs0[j] - adrs1[j];
}
/* If map_q[gp2] is smaller than current gp1, map_q[gp2] should */
/* equal to a previous gp1 for which map_triplets is already */
/* filled. So the counter is not incremented. */
gp2 = grg_get_grid_index(adrs2, D_diag);
if (map_q[gp2] < gp1) {
map_triplets[gp1] = map_q[gp2];
} else {
map_triplets[gp1] = gp1;
num_ir_triplets++;
}
}
}
}
grg_get_grid_address_from_index(adrs0, grid_point, D_diag);
#ifdef PHPYOPENMP
#pragma omp parallel for private(j, adrs1, adrs2)
#endif
for (i = 0; i < num_ir_q; i++)
{
grg_get_grid_address_from_index(adrs1, ir_gps_at_q[i], D_diag);
for (j = 0; j < 3; j++)
{ /* q'' */
adrs2[j] = -adrs0[j] - adrs1[j];
}
q_2[i] = grg_get_grid_index(adrs2, D_diag);
}
/* map_q[q_2[i]] is in ir_gps_at_q. */
/* If map_q[q_2[i]] < ir_gps_at_q[i], this should be already */
/* stored. So the counter is not incremented. */
for (i = 0; i < num_ir_q; i++)
{
ir_gp = ir_gps_at_q[i];
if (map_q[q_2[i]] < ir_gp)
{
map_triplets[ir_gp] = map_q[q_2[i]];
}
else
{
map_triplets[ir_gp] = ir_gp;
num_ir_triplets++;
}
}
/* Fill unfilled elements of map_triplets. */
#ifdef PHPYOPENMP
#pragma omp parallel for
#endif
for (i = 0; i < num_grid; i++)
{
map_triplets[i] = map_triplets[map_q[i]];
}
for (gp1 = 0; gp1 < num_grid; gp1++) {
if (map_q[gp1] != gp1) {
/* map_q[gp1] is one of ir-gp1, so it is already filled. */
map_triplets[gp1] = map_triplets[map_q[gp1]];
}
}
ret:
if (q_2)
{
free(q_2);
q_2 = NULL;
}
if (ir_gps_at_q)
{
free(ir_gps_at_q);
ir_gps_at_q = NULL;
}
return num_ir_triplets;
return num_ir_triplets;
}
static long get_ir_triplets_at_q_noperm(long *map_triplets,
const long *map_q,
static long get_ir_triplets_at_q_noperm(long *map_triplets, const long *map_q,
const long grid_point,
const long D_diag[3],
const RotMats *rot_reciprocal_q)
{
long i, num_grid, num_ir_triplets;
const long D_diag[3]) {
long gp1, num_grid, num_ir_triplets;
num_ir_triplets = 0;
num_grid = D_diag[0] * D_diag[1] * D_diag[2];
num_ir_triplets = 0;
num_grid = D_diag[0] * D_diag[1] * D_diag[2];
for (i = 0; i < num_grid; i++)
{
if (map_q[i] == i)
{
map_triplets[i] = i;
num_ir_triplets++;
for (gp1 = 0; gp1 < num_grid; gp1++) {
if (map_q[gp1] == gp1) {
map_triplets[gp1] = gp1;
num_ir_triplets++;
} else {
map_triplets[gp1] = map_triplets[map_q[gp1]];
}
}
else
{
map_triplets[i] = map_triplets[map_q[i]];
}
}
return num_ir_triplets;
return num_ir_triplets;
}
static long get_BZ_triplets_at_q(long (*triplets)[3],
const long grid_point,
static long get_BZ_triplets_at_q(long (*triplets)[3], const long grid_point,
const ConstBZGrid *bzgrid,
const long *map_triplets)
{
long i, num_ir;
long *ir_q1_gps;
const long *map_triplets) {
long gp1, num_ir;
long *ir_q1_gps;
ir_q1_gps = NULL;
num_ir = 0;
ir_q1_gps = NULL;
num_ir = 0;
if ((ir_q1_gps = (long *)malloc(sizeof(long) * bzgrid->size)) == NULL)
{
warning_print("Memory could not be allocated.");
goto ret;
}
for (i = 0; i < bzgrid->size; i++)
{
if (map_triplets[i] == i)
{
ir_q1_gps[num_ir] = i;
num_ir++;
if ((ir_q1_gps = (long *)malloc(sizeof(long) * bzgrid->size)) == NULL) {
warning_print("Memory could not be allocated.");
goto ret;
}
}
if (bzgrid->type == 1)
{
get_BZ_triplets_at_q_type1(triplets,
grid_point,
bzgrid,
ir_q1_gps,
num_ir);
}
else
{
get_BZ_triplets_at_q_type2(triplets,
grid_point,
bzgrid,
ir_q1_gps,
num_ir);
}
for (gp1 = 0; gp1 < bzgrid->size; gp1++) {
if (map_triplets[gp1] == gp1) {
ir_q1_gps[num_ir] = gp1;
num_ir++;
}
}
free(ir_q1_gps);
ir_q1_gps = NULL;
if (bzgrid->type == 1) {
get_BZ_triplets_at_q_type1(triplets, grid_point, bzgrid, ir_q1_gps,
num_ir);
} else {
get_BZ_triplets_at_q_type2(triplets, grid_point, bzgrid, ir_q1_gps,
num_ir);
}
free(ir_q1_gps);
ir_q1_gps = NULL;
ret:
return num_ir;
return num_ir;
}
static void get_BZ_triplets_at_q_type1(long (*triplets)[3],
const long grid_point,
const ConstBZGrid *bzgrid,
const long *ir_q1_gps,
const long num_ir)
{
long i, j, gp2, num_gp, num_bzgp, bz0, bz1, bz2;
long bzgp[3], G[3];
long bz_adrs0[3], bz_adrs1[3], bz_adrs2[3];
const long *gp_map;
const long(*bz_adrs)[3];
double d2, min_d2, tolerance;
double LQD_inv[3][3];
const long num_ir) {
long i, j, gp2, num_gp, num_bzgp, bz0, bz1, bz2;
long bzgp[3], G[3];
long bz_adrs0[3], bz_adrs1[3], bz_adrs2[3];
const long *gp_map;
const long(*bz_adrs)[3];
double d2, min_d2, tolerance;
double LQD_inv[3][3];
gp_map = bzgrid->gp_map;
bz_adrs = bzgrid->addresses;
get_LQD_inv(LQD_inv, bzgrid);
/* This tolerance is used to be consistent to BZ reduction in bzgrid. */
tolerance = bzg_get_tolerance_for_BZ_reduction((BZGrid *)bzgrid);
gp_map = bzgrid->gp_map;
bz_adrs = bzgrid->addresses;
get_LQD_inv(LQD_inv, bzgrid);
/* This tolerance is used to be consistent to BZ reduction in bzgrid. */
tolerance = bzg_get_tolerance_for_BZ_reduction((BZGrid *)bzgrid);
for (i = 0; i < 3; i++)
{
bz_adrs0[i] = bz_adrs[grid_point][i];
}
num_gp = bzgrid->D_diag[0] * bzgrid->D_diag[1] * bzgrid->D_diag[2];
num_bzgp = num_gp * 8;
for (i = 0; i < 3; i++) {
bz_adrs0[i] = bz_adrs[grid_point][i];
}
num_gp = bzgrid->D_diag[0] * bzgrid->D_diag[1] * bzgrid->D_diag[2];
num_bzgp = num_gp * 8;
#ifdef PHPYOPENMP
#pragma omp parallel for private(j, gp2, bzgp, G, bz_adrs1, bz_adrs2, d2, min_d2, bz0, bz1, bz2)
#pragma omp parallel for private(j, gp2, bzgp, G, bz_adrs1, bz_adrs2, d2, \
min_d2, bz0, bz1, bz2)
#endif
for (i = 0; i < num_ir; i++)
{
for (j = 0; j < 3; j++)
{
bz_adrs1[j] = bz_adrs[ir_q1_gps[i]][j];
bz_adrs2[j] = -bz_adrs0[j] - bz_adrs1[j];
}
gp2 = grg_get_grid_index(bz_adrs2, bzgrid->D_diag);
/* Negative value is the signal to initialize min_d2 later. */
min_d2 = -1;
for (bz0 = 0;
bz0 < gp_map[num_bzgp + grid_point + 1] - gp_map[num_bzgp + grid_point] + 1;
bz0++)
{
if (bz0 == 0)
{
bzgp[0] = grid_point;
}
else
{
bzgp[0] = num_gp + gp_map[num_bzgp + grid_point] + bz0 - 1;
}
for (bz1 = 0;
bz1 < gp_map[num_bzgp + ir_q1_gps[i] + 1] - gp_map[num_bzgp + ir_q1_gps[i]] + 1;
bz1++)
{
if (bz1 == 0)
{
bzgp[1] = ir_q1_gps[i];
for (i = 0; i < num_ir; i++) {
for (j = 0; j < 3; j++) {
bz_adrs1[j] = bz_adrs[ir_q1_gps[i]][j];
bz_adrs2[j] = -bz_adrs0[j] - bz_adrs1[j];
}
else
{
bzgp[1] = num_gp + gp_map[num_bzgp + ir_q1_gps[i]] + bz1 - 1;
}
for (bz2 = 0;
bz2 < gp_map[num_bzgp + gp2 + 1] - gp_map[num_bzgp + gp2] + 1;
bz2++)
{
if (bz2 == 0)
{
bzgp[2] = gp2;
}
else
{
bzgp[2] = num_gp + gp_map[num_bzgp + gp2] + bz2 - 1;
}
for (j = 0; j < 3; j++)
{
G[j] = bz_adrs[bzgp[0]][j] + bz_adrs[bzgp[1]][j] + bz_adrs[bzgp[2]][j];
}
if (G[0] == 0 && G[1] == 0 && G[2] == 0)
{
for (j = 0; j < 3; j++)
{
triplets[i][j] = bzgp[j];
gp2 = grg_get_grid_index(bz_adrs2, bzgrid->D_diag);
/* Negative value is the signal to initialize min_d2 later. */
min_d2 = -1;
for (bz0 = 0; bz0 < gp_map[num_bzgp + grid_point + 1] -
gp_map[num_bzgp + grid_point] + 1;
bz0++) {
if (bz0 == 0) {
bzgp[0] = grid_point;
} else {
bzgp[0] = num_gp + gp_map[num_bzgp + grid_point] + bz0 - 1;
}
goto found;
}
d2 = get_squared_distance(G, LQD_inv);
if (d2 < min_d2 - tolerance || min_d2 < 0)
{
min_d2 = d2;
for (j = 0; j < 3; j++)
{
triplets[i][j] = bzgp[j];
for (bz1 = 0; bz1 < gp_map[num_bzgp + ir_q1_gps[i] + 1] -
gp_map[num_bzgp + ir_q1_gps[i]] + 1;
bz1++) {
if (bz1 == 0) {
bzgp[1] = ir_q1_gps[i];
} else {
bzgp[1] =
num_gp + gp_map[num_bzgp + ir_q1_gps[i]] + bz1 - 1;
}
for (bz2 = 0; bz2 < gp_map[num_bzgp + gp2 + 1] -
gp_map[num_bzgp + gp2] + 1;
bz2++) {
if (bz2 == 0) {
bzgp[2] = gp2;
} else {
bzgp[2] = num_gp + gp_map[num_bzgp + gp2] + bz2 - 1;
}
for (j = 0; j < 3; j++) {
G[j] = bz_adrs[bzgp[0]][j] + bz_adrs[bzgp[1]][j] +
bz_adrs[bzgp[2]][j];
}
if (G[0] == 0 && G[1] == 0 && G[2] == 0) {
for (j = 0; j < 3; j++) {
triplets[i][j] = bzgp[j];
}
goto found;
}
d2 = get_squared_distance(G, LQD_inv);
if (d2 < min_d2 - tolerance || min_d2 < 0) {
min_d2 = d2;
for (j = 0; j < 3; j++) {
triplets[i][j] = bzgp[j];
}
}
}
}
}
}
}
found:;
}
found:;
}
}
static void get_BZ_triplets_at_q_type2(long (*triplets)[3],
const long grid_point,
const ConstBZGrid *bzgrid,
const long *ir_q1_gps,
const long num_ir)
{
long i, j, gp0, gp2;
long bzgp[3], G[3];
long bz_adrs0[3], bz_adrs1[3], bz_adrs2[3];
const long *gp_map;
const long(*bz_adrs)[3];
double d2, min_d2, tolerance;
double LQD_inv[3][3];
const long num_ir) {
long i, j, gp0, gp2;
long bzgp[3], G[3];
long bz_adrs0[3], bz_adrs1[3], bz_adrs2[3];
const long *gp_map;
const long(*bz_adrs)[3];
double d2, min_d2, tolerance;
double LQD_inv[3][3];
gp_map = bzgrid->gp_map;
bz_adrs = bzgrid->addresses;
get_LQD_inv(LQD_inv, bzgrid);
/* This tolerance is used to be consistent to BZ reduction in bzgrid. */
tolerance = bzg_get_tolerance_for_BZ_reduction((BZGrid *)bzgrid);
gp_map = bzgrid->gp_map;
bz_adrs = bzgrid->addresses;
get_LQD_inv(LQD_inv, bzgrid);
/* This tolerance is used to be consistent to BZ reduction in bzgrid. */
tolerance = bzg_get_tolerance_for_BZ_reduction((BZGrid *)bzgrid);
for (i = 0; i < 3; i++)
{
bz_adrs0[i] = bz_adrs[grid_point][i];
}
gp0 = grg_get_grid_index(bz_adrs0, bzgrid->D_diag);
for (i = 0; i < 3; i++) {
bz_adrs0[i] = bz_adrs[grid_point][i];
}
gp0 = grg_get_grid_index(bz_adrs0, bzgrid->D_diag);
#ifdef PHPYOPENMP
#pragma omp parallel for private(j, gp2, bzgp, G, bz_adrs1, bz_adrs2, d2, min_d2)
#pragma omp parallel for private(j, gp2, bzgp, G, bz_adrs1, bz_adrs2, d2, \
min_d2)
#endif
for (i = 0; i < num_ir; i++)
{
for (j = 0; j < 3; j++)
{
bz_adrs1[j] = bz_adrs[gp_map[ir_q1_gps[i]]][j];
bz_adrs2[j] = -bz_adrs0[j] - bz_adrs1[j];
}
gp2 = grg_get_grid_index(bz_adrs2, bzgrid->D_diag);
/* Negative value is the signal to initialize min_d2 later. */
min_d2 = -1;
for (bzgp[0] = gp_map[gp0]; bzgp[0] < gp_map[gp0 + 1]; bzgp[0]++)
{
for (bzgp[1] = gp_map[ir_q1_gps[i]];
bzgp[1] < gp_map[ir_q1_gps[i] + 1]; bzgp[1]++)
{
for (bzgp[2] = gp_map[gp2]; bzgp[2] < gp_map[gp2 + 1]; bzgp[2]++)
{
for (j = 0; j < 3; j++)
{
G[j] = bz_adrs[bzgp[0]][j] + bz_adrs[bzgp[1]][j] + bz_adrs[bzgp[2]][j];
}
if (G[0] == 0 && G[1] == 0 && G[2] == 0)
{
for (j = 0; j < 3; j++)
{
triplets[i][j] = bzgp[j];
}
goto found;
}
d2 = get_squared_distance(G, LQD_inv);
if (d2 < min_d2 - tolerance || min_d2 < 0)
{
min_d2 = d2;
for (j = 0; j < 3; j++)
{
triplets[i][j] = bzgp[j];
}
}
for (i = 0; i < num_ir; i++) {
for (j = 0; j < 3; j++) {
bz_adrs1[j] = bz_adrs[gp_map[ir_q1_gps[i]]][j];
bz_adrs2[j] = -bz_adrs0[j] - bz_adrs1[j];
}
}
gp2 = grg_get_grid_index(bz_adrs2, bzgrid->D_diag);
/* Negative value is the signal to initialize min_d2 later. */
min_d2 = -1;
for (bzgp[0] = gp_map[gp0]; bzgp[0] < gp_map[gp0 + 1]; bzgp[0]++) {
for (bzgp[1] = gp_map[ir_q1_gps[i]];
bzgp[1] < gp_map[ir_q1_gps[i] + 1]; bzgp[1]++) {
for (bzgp[2] = gp_map[gp2]; bzgp[2] < gp_map[gp2 + 1];
bzgp[2]++) {
for (j = 0; j < 3; j++) {
G[j] = bz_adrs[bzgp[0]][j] + bz_adrs[bzgp[1]][j] +
bz_adrs[bzgp[2]][j];
}
if (G[0] == 0 && G[1] == 0 && G[2] == 0) {
for (j = 0; j < 3; j++) {
triplets[i][j] = bzgp[j];
}
goto found;
}
d2 = get_squared_distance(G, LQD_inv);
if (d2 < min_d2 - tolerance || min_d2 < 0) {
min_d2 = d2;
for (j = 0; j < 3; j++) {
triplets[i][j] = bzgp[j];
}
}
}
}
}
found:;
}
found:;
}
}
static double get_squared_distance(const long G[3],
const double LQD_inv[3][3])
{
double d, d2;
long i;
const double LQD_inv[3][3]) {
double d, d2;
long i;
d2 = 0;
for (i = 0; i < 3; i++)
{
d = LQD_inv[i][0] * G[0] + LQD_inv[i][1] * G[1] + LQD_inv[i][2] * G[2];
d2 += d * d;
}
d2 = 0;
for (i = 0; i < 3; i++) {
d = LQD_inv[i][0] * G[0] + LQD_inv[i][1] * G[1] + LQD_inv[i][2] * G[2];
d2 += d * d;
}
return d2;
return d2;
}
static void get_LQD_inv(double LQD_inv[3][3], const ConstBZGrid *bzgrid)
{
long i, j, k;
static void get_LQD_inv(double LQD_inv[3][3], const ConstBZGrid *bzgrid) {
long i, j, k;
/* LQD^-1 */
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
for (k = 0; k < 3; k++)
{
LQD_inv[i][k] = bzgrid->reclat[i][j] * bzgrid->Q[j][k] / bzgrid->D_diag[k];
}
/* LQD^-1 */
for (i = 0; i < 3; i++) {
for (j = 0; j < 3; j++) {
for (k = 0; k < 3; k++) {
LQD_inv[i][k] =
bzgrid->reclat[i][j] * bzgrid->Q[j][k] / bzgrid->D_diag[k];
}
}
}
}
}
/* Return NULL if failed */
static RotMats *get_reciprocal_point_group_with_q(const RotMats *rot_reciprocal,
const long D_diag[3],
const long grid_point)
{
long i, num_rot, gp_rot;
long *ir_rot;
long adrs[3], adrs_rot[3];
RotMats *rot_reciprocal_q;
const long grid_point) {
long i, num_rot, gp_rot;
long *ir_rot;
long adrs[3], adrs_rot[3];
RotMats *rot_reciprocal_q;
ir_rot = NULL;
rot_reciprocal_q = NULL;
num_rot = 0;
ir_rot = NULL;
rot_reciprocal_q = NULL;
num_rot = 0;
grg_get_grid_address_from_index(adrs, grid_point, D_diag);
grg_get_grid_address_from_index(adrs, grid_point, D_diag);
if ((ir_rot = (long *)malloc(sizeof(long) * rot_reciprocal->size)) == NULL)
{
warning_print("Memory of ir_rot could not be allocated.");
return NULL;
}
for (i = 0; i < rot_reciprocal->size; i++)
{
ir_rot[i] = -1;
}
for (i = 0; i < rot_reciprocal->size; i++)
{
lagmat_multiply_matrix_vector_l3(adrs_rot, rot_reciprocal->mat[i], adrs);
gp_rot = grg_get_grid_index(adrs_rot, D_diag);
if (gp_rot == grid_point)
{
ir_rot[num_rot] = i;
num_rot++;
if ((ir_rot = (long *)malloc(sizeof(long) * rot_reciprocal->size)) ==
NULL) {
warning_print("Memory of ir_rot could not be allocated.");
return NULL;
}
}
if ((rot_reciprocal_q = bzg_alloc_RotMats(num_rot)) != NULL)
{
for (i = 0; i < num_rot; i++)
{
lagmat_copy_matrix_l3(rot_reciprocal_q->mat[i],
rot_reciprocal->mat[ir_rot[i]]);
for (i = 0; i < rot_reciprocal->size; i++) {
ir_rot[i] = -1;
}
}
for (i = 0; i < rot_reciprocal->size; i++) {
lagmat_multiply_matrix_vector_l3(adrs_rot, rot_reciprocal->mat[i],
adrs);
gp_rot = grg_get_grid_index(adrs_rot, D_diag);
free(ir_rot);
ir_rot = NULL;
if (gp_rot == grid_point) {
ir_rot[num_rot] = i;
num_rot++;
}
}
return rot_reciprocal_q;
if ((rot_reciprocal_q = bzg_alloc_RotMats(num_rot)) != NULL) {
for (i = 0; i < num_rot; i++) {
lagmat_copy_matrix_l3(rot_reciprocal_q->mat[i],
rot_reciprocal->mat[ir_rot[i]]);
}
}
free(ir_rot);
ir_rot = NULL;
return rot_reciprocal_q;
}
static RotMats *get_reciprocal_point_group(const long (*rec_rotations_in)[3][3],
const long num_rot,
const long is_time_reversal,
const long is_transpose)
{
long i, num_rot_out;
long rec_rotations_out[48][3][3];
RotMats *rec_rotations;
const long is_transpose) {
long i, num_rot_out;
long rec_rotations_out[48][3][3];
RotMats *rec_rotations;
num_rot_out = grg_get_reciprocal_point_group(rec_rotations_out,
rec_rotations_in,
num_rot,
is_time_reversal,
is_transpose);
if (num_rot_out == 0)
{
return NULL;
}
num_rot_out =
grg_get_reciprocal_point_group(rec_rotations_out, rec_rotations_in,
num_rot, is_time_reversal, is_transpose);
if (num_rot_out == 0) {
return NULL;
}
rec_rotations = bzg_alloc_RotMats(num_rot_out);
for (i = 0; i < num_rot_out; i++)
{
lagmat_copy_matrix_l3(rec_rotations->mat[i], rec_rotations_out[i]);
}
rec_rotations = bzg_alloc_RotMats(num_rot_out);
for (i = 0; i < num_rot_out; i++) {
lagmat_copy_matrix_l3(rec_rotations->mat[i], rec_rotations_out[i]);
}
return rec_rotations;
return rec_rotations;
}

View File

@ -37,18 +37,15 @@
#ifndef __triplet_grid_H__
#define __triplet_grid_H__
#include "bzgrid.h"
#include "lagrid.h"
long tpk_get_ir_triplets_at_q(long *map_triplets,
long *map_q,
const long grid_point,
const long D_diag[3],
long tpk_get_ir_triplets_at_q(long *map_triplets, long *map_q,
const long grid_point, const long D_diag[3],
const long is_time_reversal,
const long (*rec_rotations_in)[3][3],
const long num_rot,
const long swappable);
long tpk_get_BZ_triplets_at_q(long (*triplets)[3],
const long grid_point,
const long num_rot, const long swappable);
long tpk_get_BZ_triplets_at_q(long (*triplets)[3], const long grid_point,
const ConstBZGrid *bzgrid,
const long *map_triplets);

View File

@ -32,270 +32,208 @@
/* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
/* POSSIBILITY OF SUCH DAMAGE. */
#include "triplet_iw.h"
#include <math.h>
#include "grgrid.h"
#include "phonoc_utils.h"
#include "triplet.h"
#include "triplet_iw.h"
#include "tetrahedron_method.h"
#include "triplet.h"
static void set_freq_vertices(double freq_vertices[3][24][4],
const double *frequencies1,
const double *frequencies2,
const long vertices[2][24][4],
const long num_band1,
const long num_band2,
const long b1,
const long b2,
const long tp_type);
static long set_g(double g[3],
const double f0,
const double freq_vertices[3][24][4],
const long max_i);
const long num_band1, const long num_band2,
const long b1, const long b2, const long tp_type);
static long set_g(double g[3], const double f0,
const double freq_vertices[3][24][4], const long max_i);
static void get_triplet_tetrahedra_vertices(
long vertices[2][24][4],
const long tp_relative_grid_address[2][24][4][3],
const long triplet[3],
const ConstBZGrid *bzgrid);
static void
get_neighboring_grid_points_type1(long *neighboring_grid_points,
const long grid_point,
const long (*relative_grid_address)[3],
const long num_relative_grid_address,
const ConstBZGrid *bzgrid);
static void
get_neighboring_grid_points_type2(long *neighboring_grid_points,
const long grid_point,
const long (*relative_grid_address)[3],
const long num_relative_grid_address,
const ConstBZGrid *bzgrid);
long vertices[2][24][4], const long tp_relative_grid_address[2][24][4][3],
const long triplet[3], const ConstBZGrid *bzgrid);
static void get_neighboring_grid_points_type1(
long *neighboring_grid_points, const long grid_point,
const long (*relative_grid_address)[3],
const long num_relative_grid_address, const ConstBZGrid *bzgrid);
static void get_neighboring_grid_points_type2(
long *neighboring_grid_points, const long grid_point,
const long (*relative_grid_address)[3],
const long num_relative_grid_address, const ConstBZGrid *bzgrid);
void tpi_get_integration_weight(double *iw,
char *iw_zero,
const double *frequency_points,
const long num_band0,
const long tp_relative_grid_address[2][24][4][3],
const long triplets[3],
const long num_triplets,
const ConstBZGrid *bzgrid,
const double *frequencies1,
const long num_band1,
const double *frequencies2,
const long num_band2,
const long tp_type,
const long openmp_per_bands)
{
long max_i, j, b1, b2, b12, num_band_prod, adrs_shift;
long vertices[2][24][4];
double g[3];
double freq_vertices[3][24][4];
void tpi_get_integration_weight(
double *iw, char *iw_zero, const double *frequency_points,
const long num_band0, const long tp_relative_grid_address[2][24][4][3],
const long triplets[3], const long num_triplets, const ConstBZGrid *bzgrid,
const double *frequencies1, const long num_band1,
const double *frequencies2, const long num_band2, const long tp_type,
const long openmp_per_bands) {
long max_i, j, b1, b2, b12, num_band_prod, adrs_shift;
long vertices[2][24][4];
double g[3];
double freq_vertices[3][24][4];
get_triplet_tetrahedra_vertices(vertices,
tp_relative_grid_address,
triplets,
bzgrid);
get_triplet_tetrahedra_vertices(vertices, tp_relative_grid_address,
triplets, bzgrid);
num_band_prod = num_triplets * num_band0 * num_band1 * num_band2;
num_band_prod = num_triplets * num_band0 * num_band1 * num_band2;
/* tp_type: Type of integration weights stored */
/* */
/* g0 -> \delta(f0 - (-f1 + f2)) */
/* g1 -> \delta(f0 - (f1 - f2)) */
/* g2 -> \delta(f0 - (f1 + f2)) */
/* */
/* tp_type = 2: (g[2], g[0] - g[1]) mainly for ph-ph */
/* tp_type = 3: (g[2], g[0] - g[1], g[0] + g[1] + g[2]) mainly for ph-ph */
/* tp_type = 4: (g[0]) mainly for el-ph phonon decay, */
/* f0: ph, f1: el_i, f2: el_f */
/* tp_type: Type of integration weights stored */
/* */
/* g0 -> \delta(f0 - (-f1 + f2)) */
/* g1 -> \delta(f0 - (f1 - f2)) */
/* g2 -> \delta(f0 - (f1 + f2)) */
/* */
/* tp_type = 2: (g[2], g[0] - g[1]) mainly for ph-ph */
/* tp_type = 3: (g[2], g[0] - g[1], g[0] + g[1] + g[2]) mainly for ph-ph */
/* tp_type = 4: (g[0]) mainly for el-ph phonon decay, */
/* f0: ph, f1: el_i, f2: el_f */
if ((tp_type == 2) || (tp_type == 3))
{
max_i = 3;
}
if (tp_type == 4)
{
max_i = 1;
}
if ((tp_type == 2) || (tp_type == 3)) {
max_i = 3;
}
if (tp_type == 4) {
max_i = 1;
}
#ifdef PHPYOPENMP
#pragma omp parallel for private(j, b1, b2, adrs_shift, g, freq_vertices) if (openmp_per_bands)
#pragma omp parallel for private(j, b1, b2, adrs_shift, g, \
freq_vertices) if (openmp_per_bands)
#endif
for (b12 = 0; b12 < num_band1 * num_band2; b12++)
{
b1 = b12 / num_band2;
b2 = b12 % num_band2;
set_freq_vertices(freq_vertices, frequencies1, frequencies2,
vertices, num_band1, num_band2, b1, b2, tp_type);
for (j = 0; j < num_band0; j++)
{
adrs_shift = j * num_band1 * num_band2 + b1 * num_band2 + b2;
iw_zero[adrs_shift] = set_g(g, frequency_points[j], freq_vertices, max_i);
if (tp_type == 2)
{
iw[adrs_shift] = g[2];
adrs_shift += num_band_prod;
iw[adrs_shift] = g[0] - g[1];
}
if (tp_type == 3)
{
iw[adrs_shift] = g[2];
adrs_shift += num_band_prod;
iw[adrs_shift] = g[0] - g[1];
adrs_shift += num_band_prod;
iw[adrs_shift] = g[0] + g[1] + g[2];
}
if (tp_type == 4)
{
iw[adrs_shift] = g[0];
}
for (b12 = 0; b12 < num_band1 * num_band2; b12++) {
b1 = b12 / num_band2;
b2 = b12 % num_band2;
set_freq_vertices(freq_vertices, frequencies1, frequencies2, vertices,
num_band1, num_band2, b1, b2, tp_type);
for (j = 0; j < num_band0; j++) {
adrs_shift = j * num_band1 * num_band2 + b1 * num_band2 + b2;
iw_zero[adrs_shift] =
set_g(g, frequency_points[j], freq_vertices, max_i);
if (tp_type == 2) {
iw[adrs_shift] = g[2];
adrs_shift += num_band_prod;
iw[adrs_shift] = g[0] - g[1];
}
if (tp_type == 3) {
iw[adrs_shift] = g[2];
adrs_shift += num_band_prod;
iw[adrs_shift] = g[0] - g[1];
adrs_shift += num_band_prod;
iw[adrs_shift] = g[0] + g[1] + g[2];
}
if (tp_type == 4) {
iw[adrs_shift] = g[0];
}
}
}
}
}
void tpi_get_integration_weight_with_sigma(double *iw,
char *iw_zero,
const double sigma,
const double cutoff,
const double *frequency_points,
const long num_band0,
const long triplet[3],
const long const_adrs_shift,
const double *frequencies,
const long num_band,
const long tp_type,
const long openmp_per_bands)
{
long j, b12, b1, b2, adrs_shift;
double f0, f1, f2, g0, g1, g2;
void tpi_get_integration_weight_with_sigma(
double *iw, char *iw_zero, const double sigma, const double cutoff,
const double *frequency_points, const long num_band0, const long triplet[3],
const long const_adrs_shift, const double *frequencies, const long num_band,
const long tp_type, const long openmp_per_bands) {
long j, b12, b1, b2, adrs_shift;
double f0, f1, f2, g0, g1, g2;
#ifdef PHPYOPENMP
#pragma omp parallel for private(j, b1, b2, f0, f1, f2, g0, g1, g2, adrs_shift) if (openmp_per_bands)
#pragma omp parallel for private(j, b1, b2, f0, f1, f2, g0, g1, g2, \
adrs_shift) if (openmp_per_bands)
#endif
for (b12 = 0; b12 < num_band * num_band; b12++)
{
b1 = b12 / num_band;
b2 = b12 % num_band;
f1 = frequencies[triplet[1] * num_band + b1];
f2 = frequencies[triplet[2] * num_band + b2];
for (j = 0; j < num_band0; j++)
{
f0 = frequency_points[j];
adrs_shift = j * num_band * num_band + b1 * num_band + b2;
for (b12 = 0; b12 < num_band * num_band; b12++) {
b1 = b12 / num_band;
b2 = b12 % num_band;
f1 = frequencies[triplet[1] * num_band + b1];
f2 = frequencies[triplet[2] * num_band + b2];
for (j = 0; j < num_band0; j++) {
f0 = frequency_points[j];
adrs_shift = j * num_band * num_band + b1 * num_band + b2;
if ((tp_type == 2) || (tp_type == 3))
{
if (cutoff > 0 &&
fabs(f0 + f1 - f2) > cutoff &&
fabs(f0 - f1 + f2) > cutoff &&
fabs(f0 - f1 - f2) > cutoff)
{
iw_zero[adrs_shift] = 1;
g0 = 0;
g1 = 0;
g2 = 0;
if ((tp_type == 2) || (tp_type == 3)) {
if (cutoff > 0 && fabs(f0 + f1 - f2) > cutoff &&
fabs(f0 - f1 + f2) > cutoff &&
fabs(f0 - f1 - f2) > cutoff) {
iw_zero[adrs_shift] = 1;
g0 = 0;
g1 = 0;
g2 = 0;
} else {
iw_zero[adrs_shift] = 0;
g0 = phonoc_gaussian(f0 + f1 - f2, sigma);
g1 = phonoc_gaussian(f0 - f1 + f2, sigma);
g2 = phonoc_gaussian(f0 - f1 - f2, sigma);
}
if (tp_type == 2) {
iw[adrs_shift] = g2;
adrs_shift += const_adrs_shift;
iw[adrs_shift] = g0 - g1;
}
if (tp_type == 3) {
iw[adrs_shift] = g2;
adrs_shift += const_adrs_shift;
iw[adrs_shift] = g0 - g1;
adrs_shift += const_adrs_shift;
iw[adrs_shift] = g0 + g1 + g2;
}
}
if (tp_type == 4) {
if (cutoff > 0 && fabs(f0 + f1 - f2) > cutoff) {
iw_zero[adrs_shift] = 1;
iw[adrs_shift] = 0;
} else {
iw_zero[adrs_shift] = 0;
iw[adrs_shift] = phonoc_gaussian(f0 + f1 - f2, sigma);
}
}
}
else
{
iw_zero[adrs_shift] = 0;
g0 = phonoc_gaussian(f0 + f1 - f2, sigma);
g1 = phonoc_gaussian(f0 - f1 + f2, sigma);
g2 = phonoc_gaussian(f0 - f1 - f2, sigma);
}
if (tp_type == 2)
{
iw[adrs_shift] = g2;
adrs_shift += const_adrs_shift;
iw[adrs_shift] = g0 - g1;
}
if (tp_type == 3)
{
iw[adrs_shift] = g2;
adrs_shift += const_adrs_shift;
iw[adrs_shift] = g0 - g1;
adrs_shift += const_adrs_shift;
iw[adrs_shift] = g0 + g1 + g2;
}
}
if (tp_type == 4)
{
if (cutoff > 0 && fabs(f0 + f1 - f2) > cutoff)
{
iw_zero[adrs_shift] = 1;
iw[adrs_shift] = 0;
}
else
{
iw_zero[adrs_shift] = 0;
iw[adrs_shift] = phonoc_gaussian(f0 + f1 - f2, sigma);
}
}
}
}
}
void tpi_get_neighboring_grid_points(long *neighboring_grid_points,
const long grid_point,
const long (*relative_grid_address)[3],
const long num_relative_grid_address,
const ConstBZGrid *bzgrid)
{
if (bzgrid->type == 1)
{
get_neighboring_grid_points_type1(neighboring_grid_points,
grid_point,
relative_grid_address,
num_relative_grid_address,
bzgrid);
}
else
{
get_neighboring_grid_points_type2(neighboring_grid_points,
grid_point,
relative_grid_address,
num_relative_grid_address,
bzgrid);
}
const ConstBZGrid *bzgrid) {
if (bzgrid->type == 1) {
get_neighboring_grid_points_type1(neighboring_grid_points, grid_point,
relative_grid_address,
num_relative_grid_address, bzgrid);
} else {
get_neighboring_grid_points_type2(neighboring_grid_points, grid_point,
relative_grid_address,
num_relative_grid_address, bzgrid);
}
}
static void set_freq_vertices(double freq_vertices[3][24][4],
const double *frequencies1,
const double *frequencies2,
const long vertices[2][24][4],
const long num_band1,
const long num_band2,
const long b1,
const long b2,
const long tp_type)
{
long i, j;
double f1, f2;
const long num_band1, const long num_band2,
const long b1, const long b2,
const long tp_type) {
long i, j;
double f1, f2;
for (i = 0; i < 24; i++)
{
for (j = 0; j < 4; j++)
{
f1 = frequencies1[vertices[0][i][j] * num_band1 + b1];
f2 = frequencies2[vertices[1][i][j] * num_band2 + b2];
if ((tp_type == 2) || (tp_type == 3))
{
if (f1 < 0)
{
f1 = 0;
for (i = 0; i < 24; i++) {
for (j = 0; j < 4; j++) {
f1 = frequencies1[vertices[0][i][j] * num_band1 + b1];
f2 = frequencies2[vertices[1][i][j] * num_band2 + b2];
if ((tp_type == 2) || (tp_type == 3)) {
if (f1 < 0) {
f1 = 0;
}
if (f2 < 0) {
f2 = 0;
}
freq_vertices[0][i][j] = -f1 + f2;
freq_vertices[1][i][j] = f1 - f2;
freq_vertices[2][i][j] = f1 + f2;
} else {
freq_vertices[0][i][j] = -f1 + f2;
}
}
if (f2 < 0)
{
f2 = 0;
}
freq_vertices[0][i][j] = -f1 + f2;
freq_vertices[1][i][j] = f1 - f2;
freq_vertices[2][i][j] = f1 + f2;
}
else
{
freq_vertices[0][i][j] = -f1 + f2;
}
}
}
}
/* Integration weight g is calculated. */
@ -307,113 +245,87 @@ static void set_freq_vertices(double freq_vertices[3][24][4],
/* iw_zero=1 information can be used to omit to compute particles */
/* interaction strength that is often heaviest part in throughout */
/* calculation. */
static long set_g(double g[3],
const double f0,
const double freq_vertices[3][24][4],
const long max_i)
{
long i, iw_zero;
static long set_g(double g[3], const double f0,
const double freq_vertices[3][24][4], const long max_i) {
long i, iw_zero;
iw_zero = 1;
iw_zero = 1;
for (i = 0; i < max_i; i++)
{
if (thm_in_tetrahedra(f0, freq_vertices[i]))
{
g[i] = thm_get_integration_weight(f0, freq_vertices[i], 'I');
iw_zero = 0;
}
else
{
g[i] = 0;
}
}
return iw_zero;
}
static void get_triplet_tetrahedra_vertices(long vertices[2][24][4],
const long tp_relative_grid_address[2][24][4][3],
const long triplet[3],
const ConstBZGrid *bzgrid)
{
long i, j;
for (i = 0; i < 2; i++)
{
for (j = 0; j < 24; j++)
{
tpi_get_neighboring_grid_points(vertices[i][j],
triplet[i + 1],
tp_relative_grid_address[i][j],
4,
bzgrid);
}
}
}
static void
get_neighboring_grid_points_type1(long *neighboring_grid_points,
const long grid_point,
const long (*relative_grid_address)[3],
const long num_relative_grid_address,
const ConstBZGrid *bzgrid)
{
long bzmesh[3], bz_address[3];
long i, j, bz_gp, prod_bz_mesh;
for (i = 0; i < 3; i++)
{
bzmesh[i] = bzgrid->D_diag[i] * 2;
}
prod_bz_mesh = bzmesh[0] * bzmesh[1] * bzmesh[2];
for (i = 0; i < num_relative_grid_address; i++)
{
for (j = 0; j < 3; j++)
{
bz_address[j] = bzgrid->addresses[grid_point][j] + relative_grid_address[i][j];
}
bz_gp = bzgrid->gp_map[grg_get_grid_index(bz_address, bzmesh)];
if (bz_gp == prod_bz_mesh)
{
neighboring_grid_points[i] =
grg_get_grid_index(bz_address, bzgrid->D_diag);
}
else
{
neighboring_grid_points[i] = bz_gp;
}
}
}
static void
get_neighboring_grid_points_type2(long *neighboring_grid_points,
const long grid_point,
const long (*relative_grid_address)[3],
const long num_relative_grid_address,
const ConstBZGrid *bzgrid)
{
long bz_address[3];
long i, j, gp;
for (i = 0; i < num_relative_grid_address; i++)
{
for (j = 0; j < 3; j++)
{
bz_address[j] = bzgrid->addresses[grid_point][j] + relative_grid_address[i][j];
}
gp = grg_get_grid_index(bz_address, bzgrid->D_diag);
neighboring_grid_points[i] = bzgrid->gp_map[gp];
if (bzgrid->gp_map[gp + 1] - bzgrid->gp_map[gp] > 1)
{
for (j = bzgrid->gp_map[gp]; j < bzgrid->gp_map[gp + 1]; j++)
{
if (bz_address[0] == bzgrid->addresses[j][0] && bz_address[1] == bzgrid->addresses[j][1] && bz_address[2] == bzgrid->addresses[j][2])
{
neighboring_grid_points[i] = j;
break;
for (i = 0; i < max_i; i++) {
if (thm_in_tetrahedra(f0, freq_vertices[i])) {
g[i] = thm_get_integration_weight(f0, freq_vertices[i], 'I');
iw_zero = 0;
} else {
g[i] = 0;
}
}
return iw_zero;
}
static void get_triplet_tetrahedra_vertices(
long vertices[2][24][4], const long tp_relative_grid_address[2][24][4][3],
const long triplet[3], const ConstBZGrid *bzgrid) {
long i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 24; j++) {
tpi_get_neighboring_grid_points(vertices[i][j], triplet[i + 1],
tp_relative_grid_address[i][j], 4,
bzgrid);
}
}
}
static void get_neighboring_grid_points_type1(
long *neighboring_grid_points, const long grid_point,
const long (*relative_grid_address)[3],
const long num_relative_grid_address, const ConstBZGrid *bzgrid) {
long bzmesh[3], bz_address[3];
long i, j, bz_gp, prod_bz_mesh;
for (i = 0; i < 3; i++) {
bzmesh[i] = bzgrid->D_diag[i] * 2;
}
prod_bz_mesh = bzmesh[0] * bzmesh[1] * bzmesh[2];
for (i = 0; i < num_relative_grid_address; i++) {
for (j = 0; j < 3; j++) {
bz_address[j] =
bzgrid->addresses[grid_point][j] + relative_grid_address[i][j];
}
bz_gp = bzgrid->gp_map[grg_get_grid_index(bz_address, bzmesh)];
if (bz_gp == prod_bz_mesh) {
neighboring_grid_points[i] =
grg_get_grid_index(bz_address, bzgrid->D_diag);
} else {
neighboring_grid_points[i] = bz_gp;
}
}
}
static void get_neighboring_grid_points_type2(
long *neighboring_grid_points, const long grid_point,
const long (*relative_grid_address)[3],
const long num_relative_grid_address, const ConstBZGrid *bzgrid) {
long bz_address[3];
long i, j, gp;
for (i = 0; i < num_relative_grid_address; i++) {
for (j = 0; j < 3; j++) {
bz_address[j] =
bzgrid->addresses[grid_point][j] + relative_grid_address[i][j];
}
gp = grg_get_grid_index(bz_address, bzgrid->D_diag);
neighboring_grid_points[i] = bzgrid->gp_map[gp];
if (bzgrid->gp_map[gp + 1] - bzgrid->gp_map[gp] > 1) {
for (j = bzgrid->gp_map[gp]; j < bzgrid->gp_map[gp + 1]; j++) {
if (bz_address[0] == bzgrid->addresses[j][0] &&
bz_address[1] == bzgrid->addresses[j][1] &&
bz_address[2] == bzgrid->addresses[j][2]) {
neighboring_grid_points[i] = j;
break;
}
}
}
}
}
}
}

View File

@ -35,38 +35,24 @@
#ifndef __triplet_iw_H__
#define __triplet_iw_H__
void
tpi_get_integration_weight(double *iw,
char *iw_zero,
const double *frequency_points,
const long num_band0,
const long tp_relative_grid_address[2][24][4][3],
const long triplets[3],
const long num_triplets,
const ConstBZGrid *bzgrid,
const double *frequencies1,
const long num_band1,
const double *frequencies2,
const long num_band2,
const long tp_type,
const long openmp_per_bands);
void tpi_get_integration_weight_with_sigma(double *iw,
char *iw_zero,
const double sigma,
const double cutoff,
const double *frequency_points,
const long num_band0,
const long triplet[3],
const long const_adrs_shift,
const double *frequencies,
const long num_band,
const long tp_type,
const long openmp_per_bands);
void
tpi_get_neighboring_grid_points(long *neighboring_grid_points,
const long grid_point,
const long (*relative_grid_address)[3],
const long num_relative_grid_address,
const ConstBZGrid *bzgrid);
#include "bzgrid.h"
void tpi_get_integration_weight(
double *iw, char *iw_zero, const double *frequency_points,
const long num_band0, const long tp_relative_grid_address[2][24][4][3],
const long triplets[3], const long num_triplets, const ConstBZGrid *bzgrid,
const double *frequencies1, const long num_band1,
const double *frequencies2, const long num_band2, const long tp_type,
const long openmp_per_bands);
void tpi_get_integration_weight_with_sigma(
double *iw, char *iw_zero, const double sigma, const double cutoff,
const double *frequency_points, const long num_band0, const long triplet[3],
const long const_adrs_shift, const double *frequencies, const long num_band,
const long tp_type, const long openmp_per_bands);
void tpi_get_neighboring_grid_points(long *neighboring_grid_points,
const long grid_point,
const long (*relative_grid_address)[3],
const long num_relative_grid_address,
const ConstBZGrid *bzgrid);
#endif

View File

@ -2530,6 +2530,7 @@ class Phono3py:
def _set_mesh_numbers(self, mesh):
# initialization related to mesh
self._interaction = None
self._bz_grid = BZGrid(
mesh,
lattice=self._primitive.cell,

View File

@ -608,15 +608,16 @@ def get_grid_points_by_rotations(
bz_grid : BZGrid
Data structure to represent BZ grid.
reciprocal_rotations : array_like or None, optional
Rotation matrices {R} with respect to reciprocal basis vectors.
Defined by q'=Rq.
Rotation matrices {R} with respect to basis vectors of GR-grid.
Defined by g'=Rg, where g is the grid point address represented by
three integers in BZ-grid.
dtype='int_', shape=(rotations, 3, 3)
with_surface : Bool, optional
This parameter affects to how to treat grid points on BZ surface.
When False, rotated BZ surface points are moved to representative
ones among translationally equivalent points to hold one-to-one
correspondence to GR grid points. With True, BZ grid point indices
having the rotated grid addresses are returned. Default is False.
having the rotated grid addresses are returned. Default is False.
Returns
-------

View File

@ -181,55 +181,129 @@ class CollisionMatrix(ImagSelfEnergy):
)
def _run_py_collision_matrix(self):
r"""Sum over rotations, and q-points and bands for third phonons.
\Omega' = \sum_R' R' \Omega_{kp,R'k'p'}
pp_strength.shape = (num_triplets, num_band0, num_band, num_band)
"""
num_band0 = self._pp_strength.shape[1]
num_band = self._pp_strength.shape[2]
gp2tp_map = self._get_gp2tp_map()
gp2tp, tp2s, swapped = self._get_gp2tp_map()
for i in range(self._num_ir_grid_points):
r_gps = self._rot_grid_points[i]
for r, r_gp in zip(self._rotations_cartesian, r_gps):
ti = gp2tp_map[self._triplets_map_at_q[r_gp]]
inv_sinh = self._get_inv_sinh(r_gp, gp2tp_map)
for j, k in list(np.ndindex((num_band0, num_band))):
collision = (
self._pp_strength[ti, j, k] * inv_sinh * self._g[2, ti, j, k]
).sum()
inv_sinh = self._get_inv_sinh(tp2s[r_gp])
ti = gp2tp[r_gp]
for j, k in np.ndindex((num_band0, num_band)):
if swapped[r_gp]:
collision = (
self._pp_strength[ti, j, :, k]
* inv_sinh
* self._g[2, ti, j, :, k]
).sum()
else:
collision = (
self._pp_strength[ti, j, k]
* inv_sinh
* self._g[2, ti, j, k]
).sum()
collision *= self._unit_conversion
self._collision_matrix[j, :, i, k, :] += collision * r
def _run_py_reducible_collision_matrix(self):
r"""Sum over q-points and bands of third phonons.
This corresponds to the second term of right hand side of
\Omega_{q0p0, q1p1} in Chaput's paper.
pp_strength.shape = (num_triplets, num_band0, num_band, num_band)
"""
num_mesh_points = np.prod(self._pp.mesh_numbers)
num_band0 = self._pp_strength.shape[1]
num_band = self._pp_strength.shape[2]
gp2tp_map = self._get_gp2tp_map()
for i in range(num_mesh_points):
ti = gp2tp_map[self._triplets_map_at_q[i]]
inv_sinh = self._get_inv_sinh(i, gp2tp_map)
for j, k in list(np.ndindex((num_band0, num_band))):
collision = (
self._pp_strength[ti, j, k] * inv_sinh * self._g[2, ti, j, k]
).sum()
gp2tp, tp2s, swapped = self._get_gp2tp_map()
for gp1 in range(num_mesh_points):
inv_sinh = self._get_inv_sinh(tp2s[gp1])
ti = gp2tp[gp1]
for j, k in np.ndindex((num_band0, num_band)):
if swapped[gp1]:
collision = (
self._pp_strength[ti, j, :, k]
* inv_sinh
* self._g[2, ti, j, :, k]
).sum()
else:
collision = (
self._pp_strength[ti, j, k] * inv_sinh * self._g[2, ti, j, k]
).sum()
collision *= self._unit_conversion
self._collision_matrix[j, i, k] += collision
self._collision_matrix[j, gp1, k] += collision
def _get_gp2tp_map(self):
gp2tp_map = {}
count = 0
for i, j in enumerate(self._triplets_map_at_q):
if i == j:
gp2tp_map[i] = count
count += 1
"""Return mapping table from grid point index to triplet index.
return gp2tp_map
triplets_map_at_q contains index mapping of q1 in (q0, q1, q2) to
independet q1 under q0+q1+q2=G with a fixed q0.
def _get_inv_sinh(self, gp, gp2tp_map):
ti = gp2tp_map[self._triplets_map_at_q[gp]]
tp = self._triplets_at_q[ti]
if self._triplets_map_at_q[gp] == self._ir_map_at_q[gp]:
gp2 = tp[2]
else:
gp2 = tp[1]
freqs = self._frequencies[gp2]
Note
----
map_q[gp1] <= gp1.:
Symmetry relation of grid poi nts with a stabilizer q0.
map_triplets[gp1] <= gp1 :
map_q[gp1] == gp1 : map_q[gp2] if map_q[gp2] < gp1 otherwise gp1.
map_q[gp1] != gp1 : map_triplets[map_q[gp1]]
As a rule
1. map_triplets[gp1] == gp1 : [gp0, gp1, gp2]
2. map_triplets[gp1] != gp1 : [gp0, map_q[gp2], gp1'],
map_triplets[gp1] == map_q[gp2]
"""
map_triplets = self._triplets_map_at_q
map_q = self._ir_map_at_q
gp2tp = -np.ones(len(map_triplets), dtype="int_")
tp2s = -np.ones(len(map_triplets), dtype="int_")
swapped = np.zeros(len(map_triplets), dtype="bytes")
num_tps = 0
bzg2grg = self._pp.bz_grid.bzg2grg
for gp1, tp_gp1 in enumerate(map_triplets):
if map_q[gp1] == gp1:
if gp1 == tp_gp1:
gp2tp[gp1] = num_tps
tp2s[gp1] = self._triplets_at_q[num_tps][2]
assert bzg2grg[self._triplets_at_q[num_tps][1]] == gp1
num_tps += 1
else: # q1 <--> q2 swap if swappable.
gp2tp[gp1] = gp2tp[tp_gp1]
tp2s[gp1] = self._triplets_at_q[gp2tp[gp1]][1]
swapped[gp1] = 1
assert map_q[bzg2grg[self._triplets_at_q[gp2tp[gp1]][2]]] == gp1
else: # q1 is not in ir-q1s.
gp2tp[gp1] = gp2tp[map_q[gp1]]
tp2s[gp1] = tp2s[map_q[gp1]]
swapped[gp1] = swapped[map_q[gp1]]
# Alternative implementation of tp2s
# grg2bzg = self._pp.bz_grid.grg2bzg
# addresses = self._pp.bz_grid.addresses
# q0 = addresses[self._triplets_at_q[0][0]]
# q1 = addresses[grg2bzg[gp1]]
# q2 = -q0 - q1
# gp2 = get_grid_point_from_address(q2, self._pp.bz_grid.D_diag)
# tp2s[gp1] = self._pp.bz_grid.grg2bzg[gp2]
return gp2tp, tp2s, swapped
def _get_inv_sinh(self, gp):
"""Return sinh term for bands at a q-point."""
freqs = self._frequencies[gp]
sinh = np.where(
freqs > self._cutoff_frequency,
np.sinh(freqs * THzToEv / (2 * Kb * self._temperature)),

View File

@ -264,10 +264,6 @@ class Conductivity(ConductivityBase):
self._grid_point_count += 1
return self._grid_point_count - 1
def next(self):
"""For backward compatibility."""
return self.__next__()
@property
def mesh_numbers(self):
"""Return mesh numbers of GR-grid."""

View File

@ -58,7 +58,7 @@ from phono3py.phonon3.interaction import Interaction
from phono3py.phonon.grid import get_grid_points_by_rotations
class Conductivity_LBTE(Conductivity):
class ConductivityLBTE(Conductivity):
"""Lattice thermal conductivity calculation by direct solution."""
def __init__(
@ -164,7 +164,11 @@ class Conductivity_LBTE(Conductivity):
self._allocate_values()
def set_kappa_at_sigmas(self):
"""Calculate lattice thermal conductivity from collision matrix."""
"""Calculate lattice thermal conductivity from collision matrix.
This method is called after all elements of collision matrix are filled.
"""
if len(self._grid_points) != len(self._ir_grid_points):
print("Collision matrix is not well created.")
import sys
@ -491,22 +495,26 @@ class Conductivity_LBTE(Conductivity):
self._pp.bz_grid.grg2bzg[i], self._pp.bz_grid
)
]
self._expand_collisions(ir_gr_grid_points, rot_grid_points)
self._expand_reducible_collisions(ir_gr_grid_points, rot_grid_points)
self._expand_local_values(ir_gr_grid_points, rot_grid_points)
self._combine_reducible_collisions()
weights = np.ones(np.prod(self._pp.mesh_numbers), dtype="int_")
self._symmetrize_collision_matrix()
else:
self._combine_collisions()
weights = self._get_weights()
for i, w_i in enumerate(weights):
for j, w_j in enumerate(weights):
self._collision_matrix[:, :, i, :, :, j, :, :] *= w_i * w_j
weights = self._multiply_weights_to_collisions()
self._average_collision_matrix_by_degeneracy()
self._symmetrize_collision_matrix()
return weights
def _multiply_weights_to_collisions(self):
weights = self._get_weights()
for i, w_i in enumerate(weights):
for j, w_j in enumerate(weights):
self._collision_matrix[:, :, i, :, :, j, :, :] *= w_i * w_j
return weights
def _set_kappa_at_sigmas(self, weights):
"""Calculate thermal conductivity from collision matrix."""
for j, sigma in enumerate(self._sigmas):
@ -556,7 +564,7 @@ class Conductivity_LBTE(Conductivity):
def _combine_collisions(self):
"""Include diagonal elements into collision matrix."""
num_band = len(self._pp.primitive) * 3
for j, k in list(np.ndindex((len(self._sigmas), len(self._temperatures)))):
for j, k in np.ndindex((len(self._sigmas), len(self._temperatures))):
for i, ir_gp in enumerate(self._ir_grid_points):
for r, r_gp in zip(self._rotations_cartesian, self._rot_grid_points[i]):
if ir_gp != r_gp:
@ -573,13 +581,13 @@ class Conductivity_LBTE(Conductivity):
num_band = len(self._pp.primitive) * 3
num_mesh_points = np.prod(self._pp.mesh_numbers)
for j, k in list(np.ndindex((len(self._sigmas), len(self._temperatures)))):
for j, k in np.ndindex((len(self._sigmas), len(self._temperatures))):
for i in range(num_mesh_points):
main_diagonal = self._get_main_diagonal(i, j, k)
for ll in range(num_band):
self._collision_matrix[j, k, i, ll, i, ll] += main_diagonal[ll]
def _expand_collisions(self, ir_gr_grid_points, rot_grid_points):
def _expand_reducible_collisions(self, ir_gr_grid_points, rot_grid_points):
"""Fill elements of full collision matrix by symmetry."""
start = time.time()
if self._log_level:
@ -866,12 +874,16 @@ class Conductivity_LBTE(Conductivity):
(Y / 2).reshape(num_grid_points, num_band * 3).T / weights
).T.reshape(self._f_vectors.shape)
def _get_eigvals_pinv(self, i_sigma, i_temp):
def _get_eigvals_pinv(self, i_sigma, i_temp, take_abs=True):
"""Return inverse eigenvalues of eigenvalues > epsilon."""
w = self._collision_eigenvalues[i_sigma, i_temp]
e = np.zeros_like(w)
for ll, val in enumerate(w):
if abs(val) > self._pinv_cutoff:
if take_abs:
_val = abs(val)
else:
_val = val
if _val > self._pinv_cutoff:
e[ll] = 1 / val
return e
@ -1291,7 +1303,7 @@ def get_thermal_conductivity_LBTE(
else:
temps = _temperatures
lbte = Conductivity_LBTE(
lbte = ConductivityLBTE(
interaction,
grid_points=grid_points,
temperatures=temps,
@ -1333,6 +1345,7 @@ def get_thermal_conductivity_LBTE(
text = (" %.1f " * len(temps_read)) % tuple(temps_read)
print("Temperature: " + text)
# This computes pieces of collision matrix sequentially.
for i in lbte:
if write_pp:
_write_pp(
@ -1363,6 +1376,7 @@ def get_thermal_conductivity_LBTE(
if grid_points is None and all_bands_exist(interaction):
lbte.set_kappa_at_sigmas()
if write_kappa:
_write_kappa(
lbte,
@ -1379,17 +1393,17 @@ def get_thermal_conductivity_LBTE(
def _write_collision(
lbte,
interaction,
lbte: ConductivityLBTE,
interaction: Interaction,
i=None,
is_reducible_collision_matrix=False,
is_one_gp_colmat=False,
filename=None,
):
grid_points = lbte.get_grid_points()
grid_points = lbte.grid_points
temperatures = lbte.temperatures
sigmas = lbte.get_sigmas()
sigma_cutoff = lbte.get_sigma_cutoff_width()
sigmas = lbte.sigmas
sigma_cutoff = lbte.sigma_cutoff_width
gamma = lbte.gamma
gamma_isotope = lbte.gamma_isotope
collision_matrix = lbte.collision_matrix
@ -1459,7 +1473,7 @@ def _write_collision(
def _write_kappa(
lbte,
lbte: ConductivityLBTE,
volume,
is_reducible_collision_matrix=False,
write_LBTE_solution=False,

View File

@ -53,7 +53,7 @@ from phono3py.phonon3.triplets import get_all_triplets
from phono3py.phonon.grid import get_grid_points_by_rotations
class Conductivity_RTA(Conductivity):
class ConductivityRTA(Conductivity):
"""Lattice thermal conductivity calculation with RTA."""
def __init__(
@ -609,7 +609,7 @@ def get_thermal_conductivity_RTA(
"-------------------- Lattice thermal conducitivity (RTA) "
"--------------------"
)
br = Conductivity_RTA(
br = ConductivityRTA(
interaction,
grid_points=grid_points,
temperatures=_temperatures,

View File

@ -297,8 +297,8 @@ def get_smallest_vector_of_atom_pair(
def _get_orbits(atom_index, cell, site_symmetry, symprec=1e-5):
lattice = cell.get_cell().T
positions = cell.get_scaled_positions()
lattice = cell.cell.T
positions = cell.scaled_positions
center = positions[atom_index]
# orbits[num_atoms, num_site_sym]

View File

@ -351,9 +351,9 @@ def _get_constrained_fc2(
'forces': []}, ...]
"""
lattice = supercell.get_cell().T
positions = supercell.get_scaled_positions()
num_atom = supercell.get_number_of_atoms()
lattice = supercell.cell.T
positions = supercell.scaled_positions
num_atom = len(supercell)
fc2 = np.zeros((num_atom, num_atom, 3, 3), dtype="double")
atom_list = np.unique([x["number"] for x in dataset_second_atoms])
@ -427,14 +427,14 @@ def _solve_fc3(
print(" [%2d %2d %2d]\n" % tuple(v[2]))
sys.stdout.flush()
lattice = supercell.get_cell().T
lattice = supercell.cell.T
site_sym_cart = np.array(
[similarity_transformation(lattice, sym) for sym in site_symmetry],
dtype="double",
order="C",
)
num_atom = supercell.get_number_of_atoms()
positions = supercell.get_scaled_positions()
num_atom = len(supercell)
positions = supercell.scaled_positions
pos_center = positions[first_atom_num].copy()
positions -= pos_center
@ -655,7 +655,7 @@ def _get_fc3_least_atoms(
else:
direction = np.dot(
dataset_first_atom["displacement"],
np.linalg.inv(supercell.get_cell()),
np.linalg.inv(supercell.cell),
)
reduced_site_sym = get_reduced_site_symmetry(
site_symmetry, direction, symprec

View File

@ -499,7 +499,7 @@ class Interaction:
weights_at_q,
triplets_map_at_q,
ir_map_at_q,
) = get_triplets_at_q(grid_point, self._bz_grid)
) = get_triplets_at_q(grid_point, self._bz_grid, swappable=True)
# Special treatment of symmetry is applied when q_direction is
# used.

View File

@ -131,8 +131,8 @@ def get_nosym_triplets_at_q(grid_point, bz_grid: BZGrid):
"""
map_triplets = np.arange(np.prod(bz_grid.D_diag), dtype="int_")
map_q = np.arange(np.prod(bz_grid.D_diag), dtype="int_")
triplets_at_q, weights = _get_BZ_triplets_at_q(grid_point, bz_grid, map_triplets)
map_q = map_triplets.copy()
return triplets_at_q, weights, map_triplets, map_q

View File

@ -62,7 +62,7 @@ def plot_one_file(ax, args):
def plot_more(ax, coleigs, temperatures, args):
t_index = get_t_index(temperatures[0], args)
y = [v[t_index] for v in coleigs]
y = [np.abs(v[t_index]) for v in coleigs]
ax.semilogy(np.transpose(y), ".", markersize=5)
ax.set_xlim(0, len(y[0]))

View File

@ -1,11 +1,13 @@
"""Tests for direct solution of LBTE."""
import numpy as np
si_pbesol_kappa_LBTE = [111.802, 111.802, 111.802, 0, 0, 0]
si_pbesol_kappa_LBTE_redcol = [61.3504328, 61.3504328, 61.3504328, 0, 0, 0]
from phono3py.api_phono3py import Phono3py
si_pbesol_kappa_LBTE = [111.117, 111.117, 111.117, 0, 0, 0]
si_pbesol_kappa_LBTE_redcol = [63.019, 63.019, 63.019, 0, 0, 0]
def test_kappa_LBTE(si_pbesol):
def test_kappa_LBTE(si_pbesol: Phono3py):
"""Test for symmetry reduced collision matrix."""
si_pbesol.mesh_numbers = [9, 9, 9]
si_pbesol.init_phph_interaction()
@ -19,7 +21,7 @@ def test_kappa_LBTE(si_pbesol):
np.testing.assert_allclose(si_pbesol_kappa_LBTE, kappa, atol=0.5)
def test_kappa_LBTE_full_colmat(si_pbesol):
def test_kappa_LBTE_full_colmat(si_pbesol: Phono3py):
"""Test for full collision matrix."""
si_pbesol.mesh_numbers = [5, 5, 5]
si_pbesol.init_phph_interaction()