25#ifndef __MATCHING_COEFFICIENTS_HPP__
26#define __MATCHING_COEFFICIENTS_HPP__
28#include <gsl/gsl_sf_bessel.h>
62 std::vector<double> gkvec_len_;
80 template <int N, bool conjugate, typename T, typename = std::enable_if_t<!std::is_scalar<T>::value>>
81 inline void generate(
int ngk, std::vector<std::complex<double>>
const& phase_factors__,
int iat,
int l,
int lm,
84 std::complex<double> zt;
86 for (
int igk = 0; igk < ngk; igk++) {
89 zt =
alm_b_(0, igk, l, iat) * A(0, 0);
93 zt =
alm_b_(0, igk, l, iat) * A(nu, 0) +
alm_b_(1, igk, l, iat) * A(nu, 1);
97 zt =
alm_b_(0, igk, l, iat) * A(nu, 0) +
alm_b_(1, igk, l, iat) * A(nu, 1) +
98 alm_b_(2, igk, l, iat) * A(nu, 2);
116 int lmax_apw = unit_cell__.lmax_apw();
125 std::vector<std::complex<double>> ylm(lmmax_apw);
132 gkvec_len_[i] = vs[0];
137 for (
int lm = 0;
lm < lmmax_apw;
lm++) {
156 double RGk = R * gkvec_len_[igk];
160 gsl_sf_bessel_jl_array(lmax_apw + 1, RGk, &sbessel_mt(0, 0));
170 for (
int l = 0; l <= lmax_apw; l++) {
171 sbessel_mt(l, 1) = -sbessel_mt(l + 1, 0) * gkvec_len_[igk] + (l / R) * sbessel_mt(l, 0);
172 sbessel_mt(l, 2) = 2 * gkvec_len_[igk] * sbessel_mt(l + 1, 0) / R +
173 ((l - 1) * l - std::pow(RGk, 2)) * sbessel_mt(l, 0) / std::pow(R, 2);
176 for (
int l = 0; l <= lmax_apw; l++) {
177 std::complex<double> z = std::pow(std::complex<double>(0, 1), l);
179 alm_b_(0, igk, l, iat) = z * f * sbessel_mt(l, 0);
180 alm_b_(1, igk, l, iat) = z * f * sbessel_mt(l, 1);
181 alm_b_(2, igk, l, iat) = z * f * sbessel_mt(l, 2);
192 template <bool conjugate, typename T, typename = std::enable_if_t<!std::is_scalar<T>::value>>
195 auto& type = atom__.
type();
197 RTE_ASSERT(type.max_aw_order() <= 3);
201 std::vector<std::complex<double>> phase_factors(
gkvec_.
count());
203 double phase =
twopi * dot(
gkvec_.template gkvec<index_domain_t::local>(i), atom__.
position());
204 phase_factors[i] = std::exp(std::complex<double>(0, phase));
207 const double eps{0.1};
208 std::vector<r3::matrix<double>> Al(atom__.
type().lmax_apw() + 1);
210 for (
int l = 0; l <= atom__.
type().lmax_apw(); l++) {
212 int num_aw =
static_cast<int>(type.aw_descriptor(l).size());
215 for (
int order = 0; order < num_aw; order++) {
216 for (
int dm = 0; dm < num_aw; dm++) {
224 if (
unit_cell_.parameters().cfg().control().verification() >= 1) {
227 s <<
"Ill defined plane wave matching problem for atom type " << iat <<
", l = " << l
229 <<
" radial function value at the MT boundary : " << A(0, 0);
230 RTE_WARNING(s.str());
234 A(0, 0) = 1.0 / A(0, 0);
238 double det = A(0, 0) * A(1, 1) - A(0, 1) * A(1, 0);
240 if (
unit_cell_.parameters().cfg().control().verification() >= 1) {
243 s <<
"Ill defined plane wave matching problem for atom type " << iat <<
", l = " << l
245 <<
" radial function value at the MT boundary : " << A(0, 0);
246 RTE_WARNING(s.str());
250 std::swap(A(0, 0), A(1, 1));
253 A(0, 1) = -A(0, 1) / det;
254 A(1, 0) = -A(1, 0) / det;
265 for (
int xi = 0; xi < type.mt_aw_basis_size(); xi++) {
266 int l = type.indexb(xi).am.l();
267 int lm = type.indexb(xi).lm;
268 int nu = type.indexb(xi).order;
271 int num_aw =
static_cast<int>(type.aw_descriptor(l).size());
276 generate<1, conjugate>(
gkvec_.
count(), phase_factors, iat, l,
lm, nu, Al[l], &alm__(0, xi));
281 generate<2, conjugate>(
gkvec_.
count(), phase_factors, iat, l,
lm, nu, Al[l], &alm__(0, xi));
286 generate<3, conjugate>(
gkvec_.
count(), phase_factors, iat, l,
lm, nu, Al[l], &alm__(0, xi));
290 RTE_THROW(
"wrong order of augmented wave");
296 auto const& gkvec()
const
double aw_surface_deriv(int l__, int order__, int dm__) const
Get m-th order radial derivative of AW functions at the MT surface.
double mt_radius() const
Return muffin-tin radius.
Data and methods specific to the actual atom in the unit cell.
Atom_symmetry_class & symmetry_class()
Return reference to corresponding atom symmetry class.
Atom_type const & type() const
Return const reference to corresponding atom type object.
r3::vector< double > const & position() const
Return atom position in fractional coordinates.
Unit_cell const & unit_cell_
Description of the unit cell.
sddk::mdarray< std::complex< double >, 4 > alm_b_
Precomputed values for the linear equations for matching coefficients.
void generate(Atom const &atom__, sddk::mdarray< T, 2 > &alm__) const
Generate plane-wave matching coefficients for the radial solutions of a given atom.
sddk::mdarray< std::complex< double >, 2 > gkvec_ylm_
Spherical harmonics Ylm(theta, phi) of the G+k vectors.
fft::Gvec const & gkvec_
Description of the G+k vectors.
Matching_coefficients(Unit_cell const &unit_cell__, fft::Gvec const &gkvec__)
Constructor.
void generate(int ngk, std::vector< std::complex< double > > const &phase_factors__, int iat, int l, int lm, int nu, r3::matrix< double > const &A, T *alm) const
Generate matching coefficients for a specific and order.
Representation of a unit cell.
double omega() const
Unit cell volume.
int num_atom_types() const
Number of atom types.
Atom_type & atom_type(int id__)
Return atom type instance by id.
A set of G-vectors for FFTs and G+k basis functions.
int count() const
Number of G-vectors for a fine-grained distribution for the current MPI rank.
r3::vector< double > gkvec_cart(int ig__) const
Return G+k vector in fractional coordinates.
Multidimensional array with the column-major (Fortran) order.
void zero(memory_t mem__, size_t idx0__, size_t n__)
Zero n elements starting from idx0.
Declaration and implementation of Gvec class.
auto inverse(matrix< int > src)
Return inverse of the integer matrix.
auto spherical_coordinates(vector< double > vc)
Transform Cartesian coordinates [x,y,z] to spherical coordinates [r,theta,phi].
int lmmax(int lmax)
Maximum number of combinations for a given .
int lm(int l, int m)
Get composite lm index by angular index l and azimuthal index m.
void spherical_harmonics(int lmax, double theta, double phi, std::complex< double > *ylm)
Optimized implementation of complex spherical harmonics.
Namespace of the SIRIUS library.
auto conj(double x__)
Return complex conjugate of a number. For a real value this is the number itself.
Contains definition and partial implementation of sirius::Unit_cell class.