Files
lammps/src/ML-IAP/mliap_so3.cpp
2024-01-21 15:53:35 -05:00

1231 lines
36 KiB
C++

/* ----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------
Contributing authors: Byungkyun Kang (University of Nevada, Las Vegas)
------------------------------------------------------------------------- */
#include "mliap_so3.h"
#include "error.h"
#include "math_const.h"
#include "math_special.h"
#include "memory.h"
#include <cmath>
#include "mliap_so3_math.h"
using namespace SO3Math;
using namespace LAMMPS_NS;
using namespace MathConst;
using namespace MathSpecial;
static constexpr double SMALL = 1.0e-8;
/* ---------------------------------------------------------------------- */
MLIAP_SO3::MLIAP_SO3(LAMMPS *lmp, double vrcut, int vlmax, int vnmax, double valpha) : Pointers(lmp)
{
m_rcut = vrcut;
m_alpha = valpha;
m_lmax = vlmax;
m_nmax = vnmax;
compute_ncoeff();
m_Nmax = (m_nmax + m_lmax + 1) * 10;
m_numYlms = (m_lmax + 1) * (m_lmax + 1);
m_ellpl1 = nullptr;
m_ellm1 = nullptr;
m_pfac = nullptr;
m_dfac0 = nullptr;
m_dfac1 = nullptr;
m_dfac2 = nullptr;
m_dfac3 = nullptr;
m_dfac4 = nullptr;
m_dfac5 = nullptr;
m_g_array = nullptr;
m_w = nullptr;
m_rootpq = nullptr;
m_idxu_block = nullptr;
m_idxylm = nullptr;
m_rip_array = nullptr;
m_rip_darray = nullptr;
m_sbes_array = nullptr;
m_sbes_darray = nullptr;
m_plist_r = nullptr;
m_plist_i = nullptr;
m_clist_r = nullptr;
m_clist_i = nullptr;
m_ulist_r = nullptr;
m_ulist_i = nullptr;
m_Ylms_r = nullptr;
m_Ylms_i = nullptr;
m_dYlm_r = nullptr;
m_dYlm_i = nullptr;
m_dplist_r = nullptr;
m_dclist_r = nullptr;
m_dclist_i = nullptr;
m_tempdp_r = nullptr;
m_clisttot_r = nullptr;
m_clisttot_i = nullptr;
m_init_arrays = 0;
m_dfac_l1 = m_dfac_l2 = 0;
m_pfac_l1 = m_pfac_l2 = 0;
m_idxu_count = m_idxy_count = 0;
alloc_init = alloc_arrays = 0.0;
}
/* ---------------------------------------------------------------------- */
MLIAP_SO3::~MLIAP_SO3()
{
memory->destroy(m_ellpl1);
memory->destroy(m_ellm1);
memory->destroy(m_pfac);
memory->destroy(m_dfac0);
memory->destroy(m_pfac);
memory->destroy(m_dfac0);
memory->destroy(m_dfac1);
memory->destroy(m_dfac2);
memory->destroy(m_dfac3);
memory->destroy(m_dfac4);
memory->destroy(m_dfac5);
memory->destroy(m_w);
memory->destroy(m_g_array);
memory->destroy(m_rootpq);
memory->destroy(m_idxu_block);
memory->destroy(m_idxylm);
memory->destroy(m_rip_array);
memory->destroy(m_rip_darray);
memory->destroy(m_sbes_array);
memory->destroy(m_sbes_darray);
memory->destroy(m_plist_r);
memory->destroy(m_plist_i);
memory->destroy(m_clist_r);
memory->destroy(m_clist_i);
memory->destroy(m_ulist_r);
memory->destroy(m_ulist_i);
memory->destroy(m_Ylms_r);
memory->destroy(m_Ylms_i);
memory->destroy(m_dYlm_r);
memory->destroy(m_dYlm_i);
memory->destroy(m_dplist_r);
memory->destroy(m_dclist_r);
memory->destroy(m_dclist_i);
memory->destroy(m_tempdp_r);
memory->destroy(m_clisttot_r);
memory->destroy(m_clisttot_i);
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::compute_ncoeff()
{
ncoeff = m_nmax * (m_nmax + 1) * (m_lmax + 1) / 2;
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::init()
{
int i, totali;
totali = m_lmax + 1;
memory->destroy(m_ellpl1);
memory->create(m_ellpl1, totali, "MLIAP_SO3:m_ellpl1");
memory->destroy(m_ellm1);
memory->create(m_ellm1, totali, "MLIAP_SO3:m_ellm1");
alloc_init = 2.0 * totali * sizeof(double);
for (int l = 1; l < m_lmax + 1; l++) {
m_ellpl1[l] = get_sum(0, l + 2, 1, 2);
m_ellm1[l] = get_sum(0, l, 1, 2);
}
double pfac1 = 1.0 / 4.0 / MY_PI;
m_pfac_l1 = m_lmax + 2;
m_pfac_l2 = (m_lmax + 2) * (m_lmax + 2) + 1;
totali = m_pfac_l1 * m_pfac_l2;
memory->destroy(m_pfac);
memory->create(m_pfac, totali, "MLIAP_SO3:m_pfac");
alloc_init += totali * sizeof(double);
for (int l = 0; l < m_lmax + 2; l++)
for (int m = -l; m < l + 1; m++)
m_pfac[l * m_pfac_l2 + m] = sqrt((2.0 * l + 1.0) * pfac1) * powsign(m);
m_dfac_l1 = m_lmax + 1;
m_dfac_l2 = m_numYlms + 1;
totali = m_dfac_l1 * m_dfac_l2;
memory->destroy(m_dfac0);
memory->create(m_dfac0, totali, "MLIAP_SO3:m_dfac0");
memory->destroy(m_dfac1);
memory->create(m_dfac1, totali, "MLIAP_SO3:m_dfac1");
memory->destroy(m_dfac2);
memory->create(m_dfac2, totali, "MLIAP_SO3:m_dfac2");
memory->destroy(m_dfac3);
memory->create(m_dfac3, totali, "MLIAP_SO3:m_dfac3");
memory->destroy(m_dfac4);
memory->create(m_dfac4, totali, "MLIAP_SO3:m_dfac4");
memory->destroy(m_dfac5);
memory->create(m_dfac5, totali, "MLIAP_SO3:m_dfac5");
alloc_init += 6.0 * totali * sizeof(double);
for (int l = 1; l < m_lmax + 1; l++)
for (int m = -l; m < l + 1; m++) {
m_dfac0[l * m_dfac_l2 + m] =
-sqrt(((l + 1.0) * (l + 1.0) - m * m) / (2.0 * l + 1.0) / (2.0 * l + 3.0)) * l;
m_dfac1[l * m_dfac_l2 + m] =
sqrt((l * l - m * m) / (2.0 * l - 1.0) / (2.0 * l + 1.0)) * (l + 1.0);
m_dfac2[l * m_dfac_l2 + m] =
-sqrt((l + m + 1.0) * (l + m + 2.0) / 2.0 / (2.0 * l + 1.0) / (2.0 * l + 3.0)) * l;
m_dfac3[l * m_dfac_l2 + m] =
sqrt((l - m - 1.0) * (l - m) / 2.0 / (2.0 * l - 1.0) / (2.0 * l + 1.0)) * (l + 1.0);
m_dfac4[l * m_dfac_l2 + m] =
-sqrt((l - m + 1.0) * (l - m + 2.0) / 2.0 / (2.0 * l + 1.0) / (2.0 * l + 3.0)) * l;
m_dfac5[l * m_dfac_l2 + m] =
sqrt((l + m - 1.0) * (l + m) / 2.0 / (2.0 * l - 1.0) / (2.0 * l + 1.0)) * (l + 1.0);
}
totali = m_nmax * m_nmax;
memory->destroy(m_w);
memory->create(m_w, totali, "MLIAP_SO3:w");
alloc_init += totali * sizeof(double);
for (i = 0; i < totali; i++) m_w[i] = 0.0;
compute_W(m_nmax, m_w);
totali = m_nmax * m_Nmax;
memory->destroy(m_g_array);
memory->create(m_g_array, totali, "MLIAP_SO3:g_array");
alloc_init += totali * sizeof(double);
for (i = 0; i < totali; i++) m_g_array[i] = 0.0;
init_garray(m_nmax, m_lmax, m_rcut, m_alpha, m_w, m_nmax, m_g_array, m_Nmax);
int twolmax;
twolmax = 2 * (m_lmax + 1);
int m_ldim = twolmax + 1;
totali = m_ldim * m_ldim;
memory->destroy(m_rootpq);
memory->create(m_rootpq, totali, "MLIAP_SO3:rootpq");
alloc_init += totali * sizeof(double);
for (i = 0; i < totali; i++) m_rootpq[i] = 0.0;
for (int p = 1; p < m_ldim; p++)
for (int q = 1; q < m_ldim; q++) m_rootpq[p * m_ldim + q] = sqrt(static_cast<double>(p) / q);
memory->destroy(m_idxu_block);
memory->create(m_idxu_block, m_ldim, "MLIAP_SO3:idxu_bloc");
alloc_init += totali * sizeof(double);
for (i = 0; i < m_ldim; i++) m_idxu_block[i] = 0;
totali = square(m_lmax + 2);
memory->destroy(m_idxylm);
memory->create(m_idxylm, totali, "MLIAP_SO3:idxylm");
alloc_init += totali * sizeof(double);
for (i = 0; i < totali; i++) m_idxylm[i] = 0;
m_idxu_count = m_idxy_count = 0;
for (int l = 0; l < m_ldim; l++) {
m_idxu_block[l] = m_idxu_count;
for (int mb = 0; mb < l + 1; mb++)
for (int ma = 0; ma < l + 1; ma++) {
if (l % 2 == 0 && ma == l / 2) {
m_idxylm[m_idxy_count] = m_idxu_count;
m_idxy_count += 1;
}
m_idxu_count += 1;
}
}
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::init_arrays(int nlocal, int ncoefs)
{
int totali = nlocal * ncoefs;
memory->destroy(m_plist_r);
memory->create(m_plist_r, totali, "MLIAP_SO3:m_plist_r");
memory->destroy(m_plist_i);
memory->create(m_plist_i, totali, "MLIAP_SO3:m_plist_i");
alloc_arrays = 2.0 * totali * sizeof(double);
totali = m_nmax * m_numYlms;
memory->destroy(m_clist_r);
memory->create(m_clist_r, totali, "MLIAP_SO3:m_clist_r");
memory->destroy(m_clist_i);
memory->create(m_clist_i, totali, "MLIAP_SO3:m_clist_i");
alloc_arrays += 2.0 * totali * sizeof(double);
totali = m_idxu_count;
memory->destroy(m_ulist_r);
memory->create(m_ulist_r, totali, "MLIAP_SO3:m_ulist_r");
memory->destroy(m_ulist_i);
memory->create(m_ulist_i, totali, "MLIAP_SO3:m_ulist_i");
alloc_arrays += 2.0 * totali * sizeof(double);
totali = (m_lmax + 2) * (m_lmax + 2);
memory->destroy(m_Ylms_r);
memory->create(m_Ylms_r, totali, "MLIAP_SO3:m_Ylms_r");
memory->destroy(m_Ylms_i);
memory->create(m_Ylms_i, totali, "MLIAP_SO3:m_Ylms_i");
alloc_arrays += 2.0 * totali * sizeof(double);
totali = m_numYlms * 3;
memory->destroy(m_dYlm_r);
memory->create(m_dYlm_r, totali, "MLIAP_SO3:m_dYlm_r");
memory->destroy(m_dYlm_i);
memory->create(m_dYlm_i, totali, "MLIAP_SO3:m_dYlm_i");
alloc_arrays += 2.0 * totali * sizeof(double);
totali = m_nmax * m_numYlms * 3;
memory->destroy(m_dclist_r);
memory->create(m_dclist_r, totali, "MLIAP_SO3:m_dclist_r");
memory->destroy(m_dclist_i);
memory->create(m_dclist_i, totali, "MLIAP_SO3:m_dclist_i");
alloc_arrays += 2.0 * totali * sizeof(double);
totali = 3 * m_nmax * (m_nmax + 1) * (m_lmax + 1) / 2;
memory->destroy(m_tempdp_r);
memory->create(m_tempdp_r, totali, "MLIAP_SO3:m_tempdp_r");
alloc_arrays += totali * sizeof(double);
totali = m_nmax * m_numYlms;
memory->destroy(m_clisttot_r);
memory->create(m_clisttot_r, totali, "MLIAP_SO3:m_clisttot_r");
memory->destroy(m_clisttot_i);
memory->create(m_clisttot_i, totali, "MLIAP_SO3:m_clisttot_i");
alloc_arrays += 2.0 * totali * sizeof(double);
m_init_arrays = 1;
}
/* ---------------------------------------------------------------------- */
double MLIAP_SO3::memory_usage()
{
return alloc_init + alloc_arrays;
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::compute_W(int nmax, double *arr)
{
int alpha, beta, temp1, temp2;
for (alpha = 1; alpha < nmax + 1; alpha++) {
temp1 = (2 * alpha + 5) * (2 * alpha + 6) * (2 * alpha + 7);
for (beta = 1; beta < alpha + 1; beta++) {
temp2 = (2 * beta + 5) * (2 * beta + 6) * (2 * beta + 7);
arr[(alpha - 1) * nmax + beta - 1] =
sqrt((double)temp1 * temp2) / (5 + alpha + beta) / (6 + alpha + beta) / (7 + alpha + beta);
arr[(beta - 1) * nmax + alpha - 1] = arr[(alpha - 1) * nmax + beta - 1];
}
}
int i, j, k, n = nmax;
auto outeig = new double[n];
auto outeigvec = new double[n * n];
auto arrinv = new double[n * n];
auto sqrtD = new double[n * n];
auto tempM = new double[n * n];
auto temparr = new double *[n];
auto tempvl = new double *[n];
auto tempout = new double[n];
int info;
info = invert_matrix(n, arr, arrinv);
if (info != 0) error->all(FLERR, "Invert matrix Error in W calculation!");
for (i = 0; i < n; i++) {
temparr[i] = new double[n];
tempvl[i] = new double[n];
for (j = 0; j < n; j++) temparr[i][j] = arrinv[i * n + j];
}
jacobin(n, temparr, tempout, tempvl);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++) outeigvec[i * n + j] = tempvl[i][j];
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (i == j)
sqrtD[i * n + j] = sqrt(tempout[i]);
else
sqrtD[i * n + j] = 0.0;
double dtemp;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++) {
dtemp = 0;
for (k = 0; k < n; k++) dtemp += outeigvec[i * n + k] * sqrtD[k * n + j];
tempM[i * n + j] = dtemp;
}
info = invert_matrix(n, outeigvec, arrinv);
if (info != 0) error->all(FLERR, "Invert matrix Error in W calculation!");
for (i = 0; i < n; i++)
for (j = 0; j < n; j++) {
dtemp = 0;
for (k = 0; k < n; k++) dtemp += tempM[i * n + k] * arrinv[k * n + j];
arr[i * n + j] = dtemp;
}
delete[] outeig;
delete[] outeigvec;
delete[] arrinv;
delete[] sqrtD;
delete[] tempM;
for (i = 0; i < n; i++) {
delete[] temparr[i];
delete[] tempvl[i];
}
delete[] temparr;
delete[] tempvl;
delete[] tempout;
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::compute_pi(int nmax, int lmax, double *clisttot_r, double *clisttot_i, int lcl2,
double *plist_r, double *plist_i, int lpl2, int indpl)
{
int n1, n2, j, l, m, i = 0;
double norm;
for (n1 = 0; n1 < nmax; n1++)
for (n2 = 0; n2 < n1 + 1; n2++) {
j = 0;
for (l = 0; l < lmax + 1; l++) {
norm = 2.0 * sqrt(2.0) * MY_PI / sqrt(2.0 * l + 1.0);
for (m = -l; m < l + 1; m++) {
plist_r[lpl2 * indpl + i] += (clisttot_r[lcl2 * n1 + j] * clisttot_r[lcl2 * n2 + j] +
clisttot_i[lcl2 * n1 + j] * clisttot_i[lcl2 * n2 + j]) *
norm;
plist_i[lpl2 * indpl + i] += (-clisttot_r[lcl2 * n1 + j] * clisttot_i[lcl2 * n2 + j] +
clisttot_i[lcl2 * n1 + j] * clisttot_r[lcl2 * n2 + j]) *
norm;
j += 1;
}
i += 1;
}
}
}
/* ---------------------------------------------------------------------- */
double MLIAP_SO3::phi(double r, int alpha, double rcut)
{
return powint((rcut - r), (alpha + 2)) /
sqrt(2 * powint(rcut, (2 * alpha + 7)) / (2 * alpha + 5) / (2 * alpha + 6) / (2 * alpha + 7));
}
/* ---------------------------------------------------------------------- */
double MLIAP_SO3::compute_g(double r, int n, int nmax, double rcut, double *w, int lw1)
{
double Sum;
Sum = 0.0;
int alpha;
for (alpha = 1; alpha < nmax + 1; alpha++)
Sum += w[(n - 1) * lw1 + alpha - 1] * phi(r, alpha, rcut);
return Sum;
}
/* ---------------------------------------------------------------------- */
double MLIAP_SO3::Cosine(double Rij, double Rc)
{
return 0.5 * (cos(MY_PI * Rij / Rc) + 1.0);
}
/* ---------------------------------------------------------------------- */
double MLIAP_SO3::CosinePrime(double Rij, double Rc)
{
return -0.5 * MY_PI / Rc * sin(MY_PI * Rij / Rc);
}
/* ---------------------------------------------------------------------- */
double MLIAP_SO3::compute_sfac(double r, double rcut)
{
if (r > rcut)
return 0.0;
else
return Cosine(r, rcut);
}
/* ---------------------------------------------------------------------- */
double MLIAP_SO3::compute_dsfac(double r, double rcut)
{
if (r > rcut)
return 0.0;
else
return CosinePrime(r, rcut);
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::compute_dpidrj(int nmax, int lmax, double *clisttot_r, double *clisttot_i,
int lctot2, double *dclist_r, double *dclist_i, int ldcli2,
int ldcli3, double *dplist_r, int dpli2)
{
double temp_r;
double norm;
int i, n1, n2, j, l, m, ii;
i = 0;
for (n1 = 0; n1 < nmax; n1++)
for (n2 = 0; n2 < n1 + 1; n2++) {
j = 0;
for (l = 0; l < lmax + 1; l++) {
norm = 2.0 * sqrt(2.0) * MY_PI / sqrt(2.0 * l + 1.0);
for (m = -l; m < l + 1; m++) {
for (ii = 0; ii < 3; ii++) {
temp_r = dclist_r[(n1 * ldcli2 + j) * ldcli3 + ii] * clisttot_r[n2 * lctot2 + j] +
dclist_i[(n1 * ldcli2 + j) * ldcli3 + ii] * clisttot_i[n2 * lctot2 + j];
temp_r += clisttot_r[n1 * lctot2 + j] * dclist_r[(n2 * ldcli2 + j) * ldcli3 + ii] +
clisttot_i[n1 * lctot2 + j] * dclist_i[(n2 * ldcli2 + j) * ldcli3 + ii];
temp_r *= norm;
dplist_r[i * dpli2 + ii] += temp_r;
}
j += 1;
}
i += 1;
}
}
}
/* ---------------------------------------------------------------------- */
int MLIAP_SO3::get_sum(int istart, int iend, int id, int imult)
{
int ires = 0;
int i;
for (i = istart; i < iend; i = i + id) ires += i * imult;
return ires;
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::compute_uarray_recursive(double x, double y, double z, double r, int twol,
double *ulist_r, double *ulist_i, int *idxu_block,
double *rootpqarray)
{
int l, llu, llup, mb, ma, mbpar, mapar;
double rootpq;
int ldim = twol + 1;
double theta, phi, atheta, btheta;
double aphi_r, aphi_i, a_r, a_i, b_r, b_i;
theta = acos(z / r);
phi = atan2(y, x);
atheta = cos(theta / 2);
btheta = sin(theta / 2);
aphi_r = cos(phi / 2);
aphi_i = sin(phi / 2);
a_r = atheta * aphi_r;
a_i = atheta * aphi_i;
b_r = btheta * aphi_r;
b_i = btheta * aphi_i;
ulist_r[0] = 1.0;
ulist_i[0] = 0.0;
for (l = 1; l < ldim; l++) {
llu = idxu_block[l];
llup = idxu_block[l - 1];
mb = 0;
while (2 * mb <= l) {
ulist_r[llu] = 0.0;
ulist_i[llu] = 0.0;
for (ma = 0; ma < l; ma++) {
rootpq = rootpqarray[(l - ma) * ldim + l - mb];
ulist_r[llu] += rootpq * (a_r * ulist_r[llup] + a_i * ulist_i[llup]);
ulist_i[llu] += rootpq * (a_r * ulist_i[llup] - a_i * ulist_r[llup]);
rootpq = rootpqarray[(ma + 1) * ldim + l - mb];
ulist_r[llu + 1] += -rootpq * (b_r * ulist_r[llup] + b_i * ulist_i[llup]);
ulist_i[llu + 1] += -rootpq * (b_r * ulist_i[llup] - b_i * ulist_r[llup]);
llu += 1;
llup += 1;
}
llu += 1;
mb += 1;
}
llu = idxu_block[l];
llup = llu + (l + 1) * (l + 1) - 1;
mbpar = 1;
mb = 0;
while (2 * mb <= l) {
mapar = mbpar;
for (ma = 0; ma < l + 1; ma++) {
if (mapar == 1) {
ulist_r[llup] = ulist_r[llu];
ulist_i[llup] = -ulist_i[llu];
} else {
ulist_r[llup] = -ulist_r[llu];
ulist_i[llup] = ulist_i[llu];
}
mapar = -mapar;
llu += 1;
llup -= 1;
}
mbpar = -mbpar;
mb += 1;
}
}
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::init_garray(int nmax, int lmax, double rcut, double alpha, double *w, int lw1,
double *g_array, int lg2)
{
int i, n, Nmax = (nmax + lmax + 1) * 10;
double x, xi;
for (i = 1; i < Nmax + 1; i++) {
// roots of Chebyshev polynomial of degree N
x = cos((2 * i - 1) * MY_PI / 2 / Nmax);
// transform the interval [-1,1] to [0, rcut]
xi = rcut / 2 * (x + 1);
for (n = 1; n < nmax + 1; n++)
// r**2*g(n)(r)*e^(-alpha*r**2)
g_array[(n - 1) * lg2 + i - 1] = rcut / 2 * MY_PI / Nmax * sqrt(1 - x * x) * xi * xi *
compute_g(xi, n, nmax, rcut, w, lw1) * exp(-alpha * xi * xi);
}
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::get_sbes_array(int nlocal, int *numneighs, double **rij, int lmax, double rcut,
double alpha)
{
int i, j;
bigint neighbor;
double x, y, z, ri, xi, rb;
double sa, sb;
double pfac1, pfac2, pfac3, pfac4;
double exts;
pfac1 = alpha * rcut;
pfac4 = rcut / 2.0;
pfac3 = MY_PI / 2.0 / m_Nmax;
bigint ipair = 0;
bigint gindex;
int findex = m_Nmax * (m_lmax + 1);
const bigint mindex = m_lmax + 1;
for (int ii = 0; ii < nlocal; ii++) {
for (neighbor = 0; neighbor < numneighs[ii]; neighbor++) {
x = rij[ipair][0];
y = rij[ipair][1];
z = rij[ipair][2];
ipair++;
ri = sqrt(x * x + y * y + z * z);
if (ri < SMALL) continue;
pfac2 = pfac1 * ri;
gindex = (ipair - 1) * findex;
for (i = 1; i < m_Nmax + 1; i++) {
const bigint i1mindex = (bigint) (i - 1) * mindex;
x = cos((2 * i - 1) * pfac3);
xi = pfac4 * (x + 1);
rb = pfac2 * (x + 1);
sa = sinh(rb) / rb;
sb = (cosh(rb) - sa) / rb;
m_sbes_array[gindex + i1mindex + 0] = sa;
m_sbes_array[gindex + i1mindex + 1] = sb;
for (j = 2; j < lmax + 1; j++)
m_sbes_array[gindex + i1mindex + j] = m_sbes_array[gindex + i1mindex + j - 2] -
(2 * j - 1) / rb * m_sbes_array[gindex + i1mindex + j - 1];
exts = m_sbes_array[gindex + i1mindex + j - 2] -
(2 * j - 1) / rb * m_sbes_array[gindex + i1mindex + j - 1];
m_sbes_darray[gindex + i1mindex + 0] = sb;
for (j = 1; j < lmax; j++)
m_sbes_darray[gindex + i1mindex + j] = xi *
(j * m_sbes_array[gindex + i1mindex + j - 1] +
(j + 1) * m_sbes_array[gindex + i1mindex + j + 1]) /
(2 * j + 1);
m_sbes_darray[gindex + i1mindex + j] =
xi * (j * m_sbes_array[gindex + i1mindex + j - 1] + (j + 1) * exts) / (2 * j + 1);
m_sbes_darray[gindex + i1mindex + 0] = xi * sb;
}
}
}
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::get_rip_array(int nlocal, int *numneighs, double **rij, int nmax, int lmax,
double alpha)
{
int i, l, n;
double integrald, integral = 0.0;
bigint neighbor;
double x, y, z, ri, expfac;
bigint ipair = 0;
for (int ii = 0; ii < nlocal; ii++)
for (neighbor = 0; neighbor < numneighs[ii]; neighbor++) {
x = rij[ipair][0];
y = rij[ipair][1];
z = rij[ipair][2];
ipair++;
ri = sqrt(x * x + y * y + z * z);
if (ri < SMALL) continue;
expfac = 4 * MY_PI * exp(-alpha * ri * ri);
for (n = 1; n < nmax + 1; n++)
for (l = 0; l < lmax + 1; l++) {
integral = 0.0;
integrald = 0.0;
for (i = 0; i < m_Nmax; i++) {
integral += m_g_array[(n - 1) * m_Nmax + i] *
m_sbes_array[(ipair - 1) * m_Nmax * (m_lmax + 1) + (bigint) i * (m_lmax + 1) + l];
integrald += m_g_array[(n - 1) * m_Nmax + i] *
m_sbes_darray[(ipair - 1) * m_Nmax * (m_lmax + 1) + (bigint) i * (m_lmax + 1) + l];
}
m_rip_array[(ipair - 1) * m_nmax * (m_lmax + 1) + (bigint) (n - 1) * (m_lmax + 1) + l] =
integral * expfac;
m_rip_darray[(ipair - 1) * m_nmax * (m_lmax + 1) + (bigint) (n - 1) * (m_lmax + 1) + l] =
integrald * expfac;
}
}
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::spectrum(int nlocal, int *numneighs, int *jelems, double *wjelem, double **rij,
int nmax, int lmax, double rcut, double alpha, int ncoefs)
{
init_arrays(nlocal, ncoefs);
bigint totaln = 0;
bigint totali;
double Ylm_r, Ylm_i;
int weight, neighbor;
double x, y, z, r;
double r_int;
int twolmax = 2 * (lmax + 1);
int findex;
bigint gindex;
bigint ipair = 0;
double sfac;
findex = m_nmax * (m_lmax + 1);
for (int i = 0; i < nlocal; i++) totaln += numneighs[i];
totali = totaln * m_Nmax * (m_lmax + 1);
memory->destroy(m_sbes_array);
memory->create(m_sbes_array, totali, "MLIAP_SO3:m_sbes_array");
memory->destroy(m_sbes_darray);
memory->create(m_sbes_darray, totali, "MLIAP_SO3:m_sbes_darray");
alloc_arrays += 2.0 * totali * sizeof(double);
totali = totaln * m_nmax * (m_lmax + 1);
memory->destroy(m_rip_array);
memory->create(m_rip_array, totali, "MLIAP_SO3:m_rip_array");
memory->destroy(m_rip_darray);
memory->create(m_rip_darray, totali, "MLIAP_SO3:m_rip_darray");
alloc_arrays += 2.0 * totali * sizeof(double);
totali = totaln * ncoefs * 3;
memory->destroy(m_dplist_r);
memory->create(m_dplist_r, totali, "MLIAP_SO3:m_dplist_r");
alloc_arrays += 2.0 * totali * sizeof(double);
get_sbes_array(nlocal, numneighs, rij, lmax, rcut, alpha);
get_rip_array(nlocal, numneighs, rij, nmax, lmax, alpha);
totali = (bigint) nlocal * ncoefs;
for (int i = 0; i < totali; i++) {
m_plist_r[i] = 0.0;
m_plist_i[i] = 0.0;
}
for (int ii = 0; ii < nlocal; ii++) {
totali = (bigint) nmax * m_numYlms;
for (bigint ti = 0; ti < totali; ti++) {
m_clisttot_r[ti] = 0.0;
m_clisttot_i[ti] = 0.0;
}
for (neighbor = 0; neighbor < numneighs[ii]; neighbor++) {
const int jelem = jelems[ipair];
weight = wjelem[jelem];
x = rij[ipair][0];
y = rij[ipair][1];
z = rij[ipair][2];
ipair++;
r = sqrt(x * x + y * y + z * z);
if (r < SMALL) continue;
totali = (bigint) nmax * m_numYlms;
for (bigint ti = 0; ti < totali; ti++) {
m_clist_r[ti] = 0.0;
m_clist_i[ti] = 0.0;
}
for (bigint ti = 0; ti < m_idxu_count; ti++) {
m_ulist_r[ti] = 0.0;
m_ulist_i[ti] = 0.0;
}
compute_uarray_recursive(x, y, z, r, twolmax, m_ulist_r, m_ulist_i, m_idxu_block, m_rootpq);
sfac = compute_sfac(r, rcut);
gindex = (ipair - 1) * findex;
for (int n = 1; n < nmax + 1; n++) {
int i = 0;
for (int l = 0; l < lmax + 1; l++) {
r_int = m_rip_array[gindex + (bigint) (n - 1) * (m_lmax + 1) + l];
for (int m = -l; m < l + 1; m++) {
Ylm_r = (m_ulist_r[m_idxylm[i]]) * m_pfac[l * m_pfac_l2 + m];
m_clist_r[(n - 1) * m_numYlms + i] += r_int * Ylm_r * sfac;
Ylm_i = (m_ulist_i[m_idxylm[i]]) * m_pfac[l * m_pfac_l2 + m];
m_clist_i[(n - 1) * m_numYlms + i] += r_int * Ylm_i * sfac;
i += 1;
}
}
}
totali = (bigint) nmax * m_numYlms;
for (bigint tn = 0; tn < totali; tn++) {
m_clist_r[tn] = m_clist_r[tn] * double(weight);
m_clist_i[tn] = m_clist_i[tn] * double(weight);
}
for (bigint tn = 0; tn < totali; tn++) {
m_clisttot_r[tn] += m_clist_r[tn];
m_clisttot_i[tn] += m_clist_i[tn];
}
}
compute_pi(nmax, lmax, m_clisttot_r, m_clisttot_i, m_numYlms, m_plist_r, m_plist_i, ncoefs, ii);
}
}
/* ---------------------------------------------------------------------- */
void MLIAP_SO3::spectrum_dxdr(int nlocal, int *numneighs, int *jelems, double *wjelem, double **rij,
int nmax, int lmax, double rcut, double alpha, bigint npairs,
int ncoefs)
{
bigint totaln = 0;
bigint totali;
double dr_int[3];
double Ylm_r, Ylm_i;
double rvec[3];
double dexpfac[3];
double dfact[6];
double xcov0_r, xcov0_i, xcovpl1_r, xcovpl1_i, xcovm1_r, xcovm1_i;
double comj_i;
double r_int;
double r_int_temp;
double oneofr;
int findex;
bigint gindex;
int numps, weight, neighbor;
double x, y, z, r;
bigint ipair = 0;
bigint idpair = 0;
double sfac, dsfac, dsfac_arr[3];
findex = m_nmax * (m_lmax + 1);
for (int i = 0; i < nlocal; i++) totaln += numneighs[i];
totali = totaln * m_Nmax * (m_lmax + 1);
memory->destroy(m_sbes_array);
memory->create(m_sbes_array, totali, "MLIAP_SO3:m_sbes_array");
memory->destroy(m_sbes_darray);
memory->create(m_sbes_darray, totali, "MLIAP_SO3:m_sbes_darray");
totali = totaln * m_nmax * (m_lmax + 1);
memory->destroy(m_rip_array);
memory->create(m_rip_array, totali, "MLIAP_SO3:m_rip_array");
memory->destroy(m_rip_darray);
memory->create(m_rip_darray, totali, "MLIAP_SO3:m_rip_darray");
totali = totaln * ncoefs * 3;
memory->destroy(m_dplist_r);
memory->create(m_dplist_r, totali, "MLIAP_SO3:m_dplist_r");
totali = npairs * ncoefs * 3;
for (int i = 0; i < totali; i++) {
m_dplist_r[i] = 0.0;
}
numps = nmax * (nmax + 1) * (lmax + 1) / 2;
get_sbes_array(nlocal, numneighs, rij, lmax, rcut, alpha);
get_rip_array(nlocal, numneighs, rij, nmax, lmax, alpha);
int twolmax = 2 * (lmax + 1);
for (int ii = 0; ii < nlocal; ii++) {
totali = (bigint) nmax * m_numYlms;
for (bigint ti = 0; ti < totali; ti++) {
m_clisttot_r[ti] = 0.0;
m_clisttot_i[ti] = 0.0;
}
for (neighbor = 0; neighbor < numneighs[ii]; neighbor++) {
const int jelem = jelems[ipair];
weight = wjelem[jelem];
x = rij[ipair][0];
y = rij[ipair][1];
z = rij[ipair][2];
ipair++;
r = sqrt(x * x + y * y + z * z);
if (r < SMALL) continue;
totali = (bigint) nmax * m_numYlms;
for (bigint ti = 0; ti < totali; ti++) {
m_clist_r[ti] = 0.0;
m_clist_i[ti] = 0.0;
}
for (bigint ti = 0; ti < m_idxu_count; ti++) {
m_ulist_r[ti] = 0.0;
m_ulist_i[ti] = 0.0;
}
compute_uarray_recursive(x, y, z, r, twolmax, m_ulist_r, m_ulist_i, m_idxu_block, m_rootpq);
sfac = compute_sfac(r, rcut);
gindex = (ipair - 1) * findex;
for (int n = 1; n < nmax + 1; n++) {
int i = 0;
for (int l = 0; l < lmax + 1; l++) {
r_int = m_rip_array[gindex + (bigint) (n - 1) * (m_lmax + 1) + l];
for (int m = -l; m < l + 1; m++) {
Ylm_r = (m_ulist_r[m_idxylm[i]]) * m_pfac[l * m_pfac_l2 + m];
m_clist_r[(n - 1) * m_numYlms + i] += r_int * Ylm_r * sfac;
Ylm_i = (m_ulist_i[m_idxylm[i]]) * m_pfac[l * m_pfac_l2 + m];
m_clist_i[(n - 1) * m_numYlms + i] += r_int * Ylm_i * sfac;
i += 1;
}
}
}
totali = (bigint) nmax * m_numYlms;
for (bigint tn = 0; tn < totali; tn++) {
m_clist_r[tn] = m_clist_r[tn] * double(weight);
m_clist_i[tn] = m_clist_i[tn] * double(weight);
}
for (bigint tn = 0; tn < totali; tn++) {
m_clisttot_r[tn] += m_clist_r[tn];
m_clisttot_i[tn] += m_clist_i[tn];
}
}
for (neighbor = 0; neighbor < numneighs[ii]; neighbor++) {
const int jelem = jelems[idpair];
weight = wjelem[jelem];
x = rij[idpair][0];
y = rij[idpair][1];
z = rij[idpair][2];
idpair++;
r = sqrt(x * x + y * y + z * z);
if (r < SMALL) continue;
totali = (bigint) nmax * m_numYlms * 3;
for (bigint tn = 0; tn < totali; tn++) {
m_dclist_r[tn] = 0.0;
m_dclist_i[tn] = 0.0;
}
for (int ti = 0; ti < m_idxu_count; ti++) {
m_ulist_r[ti] = 0.0;
m_ulist_i[ti] = 0.0;
}
compute_uarray_recursive(x, y, z, r, twolmax, m_ulist_r, m_ulist_i, m_idxu_block, m_rootpq);
///////// compute_carray_wD ////////
{
rvec[0] = x;
rvec[1] = y;
rvec[2] = z;
totali = ((bigint) lmax + 2) * (lmax + 2);
for (bigint tn = 0; tn < totali; tn++) {
m_Ylms_r[tn] = 0.0;
m_Ylms_i[tn] = 0.0;
}
int i = 0;
for (int l = 0; l < lmax + 2; l++) {
for (int m = -l; m < l + 1; m++) {
m_Ylms_r[i] = (m_ulist_r[m_idxylm[i]]) * m_pfac[l * m_pfac_l2 + m];
m_Ylms_i[i] = (m_ulist_i[m_idxylm[i]]) * m_pfac[l * m_pfac_l2 + m];
i += 1;
}
}
totali = ((bigint) lmax + 1) * (lmax + 1) * 3;
for (bigint tn = 0; tn < totali; tn++) {
m_dYlm_r[tn] = 0.0;
m_dYlm_i[tn] = 0.0;
}
comj_i = 1.0 / sqrt(2.0);
oneofr = 1.0 / r;
i = 1;
for (int l = 1; l < lmax + 1; l++) {
for (int m = -l; m < l + 1; m++) {
dfact[0] = m_dfac0[l * m_dfac_l2 + m] * oneofr;
dfact[1] = m_dfac1[l * m_dfac_l2 + m] * oneofr;
dfact[2] = m_dfac2[l * m_dfac_l2 + m] * oneofr;
dfact[3] = m_dfac3[l * m_dfac_l2 + m] * oneofr;
dfact[4] = m_dfac4[l * m_dfac_l2 + m] * oneofr;
dfact[5] = m_dfac5[l * m_dfac_l2 + m] * oneofr;
xcov0_r = dfact[0] * m_Ylms_r[m_ellpl1[l] + m];
xcov0_i = dfact[0] * m_Ylms_i[m_ellpl1[l] + m];
if (abs(m) <= l - 1.0) {
xcov0_r += dfact[1] * m_Ylms_r[m_ellm1[l] + m];
xcov0_i += dfact[1] * m_Ylms_i[m_ellm1[l] + m];
}
xcovpl1_r = dfact[2] * m_Ylms_r[m_ellpl1[l] + m + 1];
xcovpl1_i = dfact[2] * m_Ylms_i[m_ellpl1[l] + m + 1];
if (abs(m + 1) <= l - 1.0) {
xcovpl1_r -= dfact[3] * m_Ylms_r[m_ellm1[l] + m + 1];
xcovpl1_i -= dfact[3] * m_Ylms_i[m_ellm1[l] + m + 1];
}
xcovm1_r = dfact[4] * m_Ylms_r[m_ellpl1[l] + m - 1];
xcovm1_i = dfact[4] * m_Ylms_i[m_ellpl1[l] + m - 1];
if (fabs(m - 1.0) <= l - 1.0) {
xcovm1_r -= dfact[5] * m_Ylms_r[m_ellm1[l] + m - 1];
xcovm1_i -= dfact[5] * m_Ylms_i[m_ellm1[l] + m - 1];
}
m_dYlm_r[i * 3 + 0] = 1.0 / sqrt(2.0) * (xcovm1_r - xcovpl1_r);
m_dYlm_r[i * 3 + 1] = -comj_i * (xcovm1_i + xcovpl1_i);
m_dYlm_r[i * 3 + 2] = xcov0_r;
m_dYlm_i[i * 3 + 0] = 1.0 / sqrt(2.0) * (xcovm1_i - xcovpl1_i);
m_dYlm_i[i * 3 + 1] = comj_i * (xcovm1_r + xcovpl1_r);
m_dYlm_i[i * 3 + 2] = xcov0_i;
i += 1;
}
}
for (int ii = 0; ii < 3; ii++) dexpfac[ii] = -2.0 * alpha * rvec[ii];
sfac = compute_sfac(r, rcut);
dsfac = compute_dsfac(r, rcut);
for (int ii = 0; ii < 3; ii++) { dsfac_arr[ii] = dsfac * rvec[ii] / r; }
for (int n = 1; n < nmax + 1; n++) {
int i = 0;
for (int l = 0; l < lmax + 1; l++) {
r_int = m_rip_array[(idpair - 1) * m_nmax * (m_lmax + 1) +
(bigint) (n - 1) * (m_lmax + 1) + l];
r_int_temp = m_rip_darray[(idpair - 1) * m_nmax * (m_lmax + 1) +
(bigint) (n - 1) * (m_lmax + 1) + l];
for (int ii = 0; ii < 3; ii++) dr_int[ii] = r_int_temp * 2.0 * alpha * rvec[ii] / r;
for (int m = -l; m < l + 1; m++) {
m_dclist_r[((n - 1) * m_numYlms + i) * 3 + 0] +=
(r_int * m_Ylms_r[i] * dexpfac[0] + dr_int[0] * m_Ylms_r[i] +
r_int * m_dYlm_r[i * 3 + 0]) *
sfac;
m_dclist_r[((n - 1) * m_numYlms + i) * 3 + 1] +=
(r_int * m_Ylms_r[i] * dexpfac[1] + dr_int[1] * m_Ylms_r[i] +
r_int * m_dYlm_r[i * 3 + 1]) *
sfac;
m_dclist_r[((n - 1) * m_numYlms + i) * 3 + 2] +=
(r_int * m_Ylms_r[i] * dexpfac[2] + dr_int[2] * m_Ylms_r[i] +
r_int * m_dYlm_r[i * 3 + 2]) *
sfac;
m_dclist_i[((n - 1) * m_numYlms + i) * 3 + 0] +=
(r_int * m_Ylms_i[i] * dexpfac[0] + dr_int[0] * m_Ylms_i[i] +
r_int * m_dYlm_i[i * 3 + 0]) *
sfac;
m_dclist_i[((n - 1) * m_numYlms + i) * 3 + 1] +=
(r_int * m_Ylms_i[i] * dexpfac[1] + dr_int[1] * m_Ylms_i[i] +
r_int * m_dYlm_i[i * 3 + 1]) *
sfac;
m_dclist_i[((n - 1) * m_numYlms + i) * 3 + 2] +=
(r_int * m_Ylms_i[i] * dexpfac[2] + dr_int[2] * m_Ylms_i[i] +
r_int * m_dYlm_i[i * 3 + 2]) *
sfac;
m_dclist_r[((n - 1) * m_numYlms + i) * 3 + 0] += (r_int * m_Ylms_r[i]) * dsfac_arr[0];
m_dclist_r[((n - 1) * m_numYlms + i) * 3 + 1] += (r_int * m_Ylms_r[i]) * dsfac_arr[1];
m_dclist_r[((n - 1) * m_numYlms + i) * 3 + 2] += (r_int * m_Ylms_r[i]) * dsfac_arr[2];
m_dclist_i[((n - 1) * m_numYlms + i) * 3 + 0] += (r_int * m_Ylms_i[i]) * dsfac_arr[0];
m_dclist_i[((n - 1) * m_numYlms + i) * 3 + 1] += (r_int * m_Ylms_i[i]) * dsfac_arr[1];
m_dclist_i[((n - 1) * m_numYlms + i) * 3 + 2] += (r_int * m_Ylms_i[i]) * dsfac_arr[2];
i += 1;
}
}
}
}
/////// end compute_carray_wD //////////////////
totali = (bigint) nmax * m_numYlms * 3;
for (bigint tn = 0; tn < totali; tn++) {
m_dclist_r[tn] = m_dclist_r[tn] * double(weight);
m_dclist_i[tn] = m_dclist_i[tn] * double(weight);
}
totali = (bigint) numps * 3;
for (bigint ti = 0; ti < totali; ti++) m_tempdp_r[ti] = 0.0;
compute_dpidrj(nmax, lmax, m_clisttot_r, m_clisttot_i, m_numYlms, m_dclist_r, m_dclist_i,
m_numYlms, 3, m_tempdp_r, 3);
for (bigint tn = 0; tn < totali; tn++)
m_dplist_r[((idpair - 1) * (numps * 3)) + tn] += m_tempdp_r[tn];
} //for(neighbor=0;neighbor<numneighs[ii];neighbor++){
} //for (int ii = 0; ii < nlocal; ii++) {
}