25#ifndef __SYMMETRIZE_MT_FUNCTION_HPP__
26#define __SYMMETRIZE_MT_FUNCTION_HPP__
29#include "function3d/spheric_function_set.hpp"
33template <
typename Index_t>
35symmetrize_mt_function(Crystal_symmetry
const& sym__, mpi::Communicator
const& comm__,
int num_mag_dims__,
36 std::vector<Spheric_function_set<double, Index_t>*> frlm__)
38 PROFILE(
"sirius::symmetrize_mt_function");
41 auto& frlm = *frlm__[0];
45 for (
auto ia : frlm.atoms()) {
46 lmmax = std::max(
lmmax, frlm[ia].angular_domain_size());
51 splindex_block<Index_t> spl_atoms(frlm.atoms().size(),
n_blocks(comm__.size()),
block_id(comm__.rank()));
57 sddk::mdarray<double, 4> fsym_loc(
lmmax, frlm.unit_cell().max_num_mt_points(), num_mag_dims__ + 1,
58 spl_atoms.local_size());
61 sddk::mdarray<double, 3> ftmp(
lmmax, frlm.unit_cell().max_num_mt_points(), num_mag_dims__ + 1);
63 double alpha = 1.0 / sym__.size();
66 for (
int i = 0; i < sym__.size(); i++) {
68 auto S = sym__[i].spin_rotation;
70 sht::rotation_matrix(
lmax, sym__[i].spg_op.euler_angles, sym__[i].spg_op.proper, rotm);
72 for (
auto it : spl_atoms) {
74 int ia = frlm.atoms()[it.i];
75 int lmmax_ia = frlm[ia].angular_domain_size();
76 int nrmax_ia = frlm.unit_cell().atom(ia).num_mt_points();
77 int ja = sym__[i].spg_op.inv_sym_atom[ia];
79 for (
int j = 0; j < num_mag_dims__ + 1; j++) {
80 la::wrap(
la::lib_t::blas).gemm(
'N',
'N', lmmax_ia, nrmax_ia, lmmax_ia, &alpha,
81 rotm.at(sddk::memory_t::host), rotm.ld(), (*frlm__[j])[ja].at(sddk::memory_t::host),
82 (*frlm__[j])[ja].ld(), &la::constant<double>::zero(),
83 ftmp.at(sddk::memory_t::host, 0, 0, j), ftmp.ld());
86 for (
int ir = 0; ir < nrmax_ia; ir++) {
87 for (
int lm = 0;
lm < lmmax_ia;
lm++) {
88 fsym_loc(
lm, ir, 0, it.li) += ftmp(
lm, ir, 0);
92 if (num_mag_dims__ == 1) {
93 for (
int ir = 0; ir < nrmax_ia; ir++) {
94 for (
int lm = 0;
lm < lmmax_ia;
lm++) {
95 fsym_loc(
lm, ir, 1, it.li) += ftmp(
lm, ir, 1) * S(2, 2);
100 if (num_mag_dims__ == 3) {
101 for (
int k : {0, 1, 2}) {
102 for (
int j : {0, 1, 2}) {
103 for (
int ir = 0; ir < nrmax_ia; ir++) {
104 for (
int lm = 0;
lm < lmmax_ia;
lm++) {
105 fsym_loc(
lm, ir, 1 + k, it.li) += ftmp(
lm, ir, 1 + j) * S(k, j);
115 double* sbuf = spl_atoms.local_size() ? fsym_loc.at(sddk::memory_t::host) :
nullptr;
116 auto ld =
static_cast<int>(fsym_loc.size(0) * fsym_loc.size(1) * fsym_loc.size(2));
118 sddk::mdarray<double, 4> fsym_glob(
lmmax, frlm.unit_cell().max_num_mt_points(), num_mag_dims__ + 1,
119 frlm.atoms().size());
121 comm__.allgather(sbuf, fsym_glob.at(sddk::memory_t::host), ld * spl_atoms.local_size(),
122 ld * spl_atoms.global_offset());
125 for (
int i = 0; i < static_cast<int>(frlm.atoms().size()); i++) {
126 int ia = frlm.atoms()[i];
127 for (
int j = 0; j < num_mag_dims__ + 1; j++) {
128 for (
int ir = 0; ir < frlm.unit_cell().atom(ia).num_mt_points(); ir++) {
129 for (
int lm = 0;
lm < frlm[ia].angular_domain_size();
lm++) {
130 (*frlm__[j])[ia](
lm, ir) = fsym_glob(
lm, ir, j, i);
Contains definition and partial implementation of sirius::Crystal_symmetry class.
int lmax(int lmmax__)
Get maximum orbital quantum number by the maximum lm index.
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.
Namespace of the SIRIUS library.
strong_type< int, struct __block_id_tag > block_id
ID of the block.
strong_type< int, struct __n_blocks_tag > n_blocks
Number of blocks to which the global index is split.