25#ifndef __SYMMETRIZE_DENSITY_MATRIX_HPP__
26#define __SYMMETRIZE_DENSITY_MATRIX_HPP__
28#include "density/density_matrix.hpp"
33apply_symmetry_to_density_matrix(sddk::mdarray<std::complex<double>, 3>
const& dm_ia__,
34 basis_functions_index
const& indexb__,
const int num_mag_comp__,
35 std::vector<sddk::mdarray<double, 2>>
const& rotm__,
36 sddk::mdarray<std::complex<double>, 2>
const& spin_rot_su2__,
37 sddk::mdarray<std::complex<double>, 3>& dm_ja__)
39 auto& indexr = indexb__.indexr();
42 for (
auto e1 : indexr) {
45 auto ss1 = am1.subshell_size();
46 auto offset1 = indexb__.index_of(e1.idxrf);
47 for (
auto e2 : indexr) {
50 auto ss2 = am2.subshell_size();
51 auto offset2 = indexb__.index_of(e2.idxrf);
54 for (
int m1 = 0; m1 < ss1; m1++) {
55 for (
int m2 = 0; m2 < ss2; m2++) {
56 std::array<std::complex<double>, 3> dm_rot_spatial = {0, 0, 0};
57 for (
int j = 0; j < num_mag_comp__; j++) {
58 for (
int m1p = 0; m1p < ss1; m1p++) {
59 for (
int m2p = 0; m2p < ss2; m2p++) {
60 dm_rot_spatial[j] += rotm__[am1.l()](m1, m1p) *
61 dm_ia__(offset1 + m1p, offset2 + m2p, j) *
62 rotm__[am2.l()](m2, m2p);
67 if (num_mag_comp__ == 1) {
68 dm_ja__(offset1 + m1, offset2 + m2, 0) += dm_rot_spatial[0];
70 std::complex<double> spin_dm[2][2] = {{dm_rot_spatial[0], dm_rot_spatial[2]},
71 {
std::conj(dm_rot_spatial[2]), dm_rot_spatial[1]}};
78 for (
int k = 0; k < num_mag_comp__; k++) {
79 for (
int is = 0; is < 2; is++) {
80 for (
int js = 0; js < 2; js++) {
81 dm_ja__(offset1 + m1, offset2 + m2, k) +=
82 spin_rot_su2__(k & 1, is) * spin_dm[is][js] *
83 std::conj(spin_rot_su2__(std::min(k, 1), js));
260 PROFILE(
"sirius::symmetrize_density_matrix");
262 auto& sym = uc__.symmetry();
265 if (sym.size() == 1) {
273 for (
int i = 0; i < sym.size(); i++) {
274 int pr = sym[i].spg_op.proper;
275 auto eang = sym[i].spg_op.euler_angles;
276 auto rotm = sht::rotation_matrix<double>(
lmax, eang, pr);
277 auto& spin_rot_su2 = sym[i].spin_rotation_su2;
279 for (
int ia = 0; ia < uc__.
num_atoms(); ia++) {
280 int ja = sym[i].spg_op.sym_atom[ia];
282 sirius::apply_symmetry_to_density_matrix(dm__[ia], uc__.
atom(ia).
type().indexb(),
283 num_mag_comp__, rotm, spin_rot_su2, dm_sym[ja]);
287 double alpha = 1.0 / double(sym.size());
289 for (
int ia = 0; ia < uc__.
num_atoms(); ia++) {
290 for (
size_t i = 0; i < dm__[ia].size(); i++) {
291 dm__[ia][i] = dm_sym[ia][i] * alpha;
Atom_type const & type() const
Return const reference to corresponding atom type object.
Representation of a unit cell.
Atom const & atom(int id__) const
Return const atom instance by id.
int lmax() const
Maximum orbital quantum number of radial functions between all atom types.
int num_atoms() const
Number of atoms in the unit cell.
int lmax(int lmmax__)
Get maximum orbital quantum number by the maximum lm index.
Namespace of the SIRIUS library.
auto conj(double x__)
Return complex conjugate of a number. For a real value this is the number itself.
void symmetrize_density_matrix(Unit_cell const &uc__, density_matrix_t &dm__, int num_mag_comp__)
Symmetrize density matrix.