|
| 1 | +#pragma once |
| 2 | +#include "irreducible_sector.h" |
| 3 | +#include "source_basis/module_ao/parallel_orbitals.h" |
| 4 | +#include "source_base/complexmatrix.h" |
| 5 | +#include "source_cell/module_symmetry/symm_rot_spin.h" |
| 6 | + |
| 7 | +namespace ModuleSymmetry |
| 8 | +{ |
| 9 | + /// @brief k-space AO-representation symmetry restoration: reconstructs D(k) at every |
| 10 | + /// k-star member from D(k_ibz), for crystal-symmetry-reduced BZ sampling. |
| 11 | + /// |
| 12 | + /// This is the LibRI-independent subset of what used to be a single |
| 13 | + /// source_lcao/module_ri/module_exx_symmetry/Symmetry_rotation class: everything needed |
| 14 | + /// to go from an irreducible-k-point density matrix to the full-BZ one, so callers that |
| 15 | + /// only need that (e.g. DFT+U's occupation-matrix/DMR restoration) do not have to depend |
| 16 | + /// on module_ri or LibRI. EXX/RPA's own real-space H(R)/RI-coefficient restoration (which |
| 17 | + /// does need RI::Tensor) is built on top of this class in |
| 18 | + /// source_lcao/module_ri/module_exx_symmetry/symm_rotation.h (ModuleSymmetry::Symmetry_rotation, |
| 19 | + /// which inherits from this one). |
| 20 | + class Symmetry_rotation_k |
| 21 | + { |
| 22 | + public: |
| 23 | + Symmetry_rotation_k() {}; |
| 24 | + virtual ~Symmetry_rotation_k() {}; |
| 25 | + |
| 26 | + //-------------------------------------------------------------------------------- |
| 27 | + // getters |
| 28 | + const std::map<Tap, std::set<TC>>& get_irreducible_sector()const { return this->irs_.get_irreducible_sector(); } |
| 29 | + TCdouble get_return_lattice(const Symmetry& symm, |
| 30 | + const ModuleBase::Matrix3& gmatd, const TCdouble gtransd, |
| 31 | + const TCdouble& posd_a1, const TCdouble& posd_a2)const |
| 32 | + { |
| 33 | + return this->irs_.get_return_lattice(symm, gmatd, gtransd, posd_a1, posd_a2); |
| 34 | + } |
| 35 | + TCdouble get_return_lattice(const int iat, const int isym) const |
| 36 | + { |
| 37 | + return this->irs_.get_return_lattice(iat, isym); |
| 38 | + } |
| 39 | + /// the rotation matrix under the basis of S_l^m. size: [nsym][lmax][nm*nm] |
| 40 | + const std::vector<std::vector<ModuleBase::ComplexMatrix>>& rotmat_Slm = this->rotmat_Slm_; |
| 41 | + const int& abfs_Lmax = this->abfs_Lmax_; |
| 42 | + //-------------------------------------------------------------------------------- |
| 43 | + // setters |
| 44 | + void find_irreducible_sector(const Symmetry& symm, const Atom* atoms, const Statistics& st, |
| 45 | + const std::vector<TC>& Rs, const TC& period, const Lattice& lat) |
| 46 | + { |
| 47 | + this->irs_.find_irreducible_sector(symm, atoms, st, Rs, period, lat); |
| 48 | + } |
| 49 | + void set_abfs_Lmax(const int l) { this->abfs_Lmax_ = l; } |
| 50 | + //-------------------------------------------------------------------------------- |
| 51 | + /// functions to contruct rotation matrix in AO-representation |
| 52 | + |
| 53 | + /// The top-level calculation interface of this class. calculate the rotation matrix in AO representation: M |
| 54 | + /// only need once call in each ion step (decided by the configuration) |
| 55 | + /// @param kstars equal k points to each ibz-kpont, corresponding to a certain symmetry operations. |
| 56 | + void cal_Ms(const K_Vectors& kv, |
| 57 | + const UnitCell& ucell, const Parallel_2D& pv); |
| 58 | + |
| 59 | + /// Use calculated M matrix to recover D(k) from D(k_ibz): D(k) = M(R, k)^\dagger D(k_ibz) M(R, k) |
| 60 | + /// the link "ik_ibz-isym-ik" can be found in kstars: k_bz = gmat[isym](k) |
| 61 | + std::vector<std::vector<std::complex<double>>>restore_dm(const K_Vectors& kv, |
| 62 | + const std::vector<std::vector<std::complex<double>>>& dm_k_ibz, |
| 63 | + const Parallel_2D& pv)const; |
| 64 | + std::vector<std::vector<double>>restore_dm(const K_Vectors& kv, |
| 65 | + const std::vector<std::vector<double>>& dm_k_ibz, |
| 66 | + const Parallel_2D& pv)const; |
| 67 | + std::vector<std::complex<double>> rot_matrix_ao(const std::vector<std::complex<double>>& DMkibz, |
| 68 | + const int ik_ibz, const int kstar_size, const int isym, const Parallel_2D& pv, const bool TRS_conj = false) const; |
| 69 | + |
| 70 | + /// (nspin=4) build the 2*nao spin operator Sigma_y = I_nao (x) sigma_y in 2d-block layout. |
| 71 | + std::vector<std::complex<double>> set_sigma_y_2d(const Parallel_2D& pv) const; |
| 72 | + |
| 73 | + /// (nspin=4) time-reversal on the spin density matrix: D(k) = sigma_y D^*(-k) sigma_y, |
| 74 | + /// realized distribution-safely as scale * Sigma_y * conj(X) * Sigma_y (X is the already |
| 75 | + /// space-group-rotated D(-k) stored in the transposed 2d-block convention). |
| 76 | + std::vector<std::complex<double>> trs_spin_rotate(const std::vector<std::complex<double>>& X, |
| 77 | + const std::vector<std::complex<double>>& sigma_y, const Parallel_2D& pv, const double scale) const; |
| 78 | + |
| 79 | + /// calculate Wigner D matrix |
| 80 | + double wigner_d(const double beta, const int l, const int m1, const int m2) const; |
| 81 | + std::complex<double> wigner_D(const TCdouble& euler_angle, const int l, const int m1, const int m2, const bool inv) const; |
| 82 | + |
| 83 | + /// c^l_{m1, m2}=<Y_l^m1|S_l^m2> |
| 84 | + std::complex<double> ovlp_Ylm_Slm(const int l, const int m1, const int m2) const; |
| 85 | + |
| 86 | + /// calculate euler angle from rotation matrix |
| 87 | + TCdouble get_euler_angle(const ModuleBase::Matrix3& gmatc) const; |
| 88 | + |
| 89 | + /// T_mm' = [c^\dagger D c]_mm', the rotation matrix in the representation of real sphere harmonics |
| 90 | + /// @param nop number of operations in gmatc; <0 means nsym_ (the unitary ones only). |
| 91 | + /// Pass nsym_+nanti_ to also build the antiunitary operations' T_l. |
| 92 | + void cal_rotmat_Slm(const ModuleBase::Matrix3* gmatc, const int lmax, const int nop); |
| 93 | + |
| 94 | + /// set a block matrix onto a 2d-parallelized matrix(col-maj), at the position (starti, startj) |
| 95 | + /// if trans=true, the block matrix is transposed before setting |
| 96 | + void set_block_to_mat2d(const int starti, const int startj, const ModuleBase::ComplexMatrix& block, |
| 97 | + std::vector<std::complex<double>>& obj_mat, const Parallel_2D& pv, const bool trans = false) const; |
| 98 | + void set_block_to_mat2d(const int starti, const int startj, const ModuleBase::ComplexMatrix& block, |
| 99 | + std::vector<double>& obj_mat, const Parallel_2D& pv, const bool trans = false) const; |
| 100 | + |
| 101 | + /// 2d-block parallized rotation matrix in AO-representation, denoted as M. |
| 102 | + /// finally we will use D(k)=M(R, k)^\dagger*D(Rk)*M(R, k) to recover D(k) from D(Rk). |
| 103 | + std::vector<std::complex<double>> contruct_2d_rot_mat_ao(const Symmetry& symm, const Atom* atoms, const Statistics& cell_st, |
| 104 | + const TCdouble& kvec_d_ibz, int isym, const Parallel_2D& pv, |
| 105 | + const SpinRotation::Su2& spin_U /*= SpinRotation::Su2{ 1.0, 0.0, 0.0, 1.0 }*/) const; |
| 106 | + |
| 107 | + std::vector<std::vector<ModuleBase::ComplexMatrix>>& get_rotmat_Slm() { return this->rotmat_Slm_; } |
| 108 | + |
| 109 | + //-------------------------------------------------------------------------------- |
| 110 | + /// list all cells in a Born-von-Karman supercell of the given period (no LibRI dependency, |
| 111 | + /// unlike RI_Util::get_Born_von_Karmen_cells which this mirrors for 3D periods). |
| 112 | + static std::vector<TC> get_bvk_cells(const TC& period); |
| 113 | + |
| 114 | + protected: |
| 115 | + int nsym_ = 1; |
| 116 | + /// (nspin=4, magnetic) number of ANTIUNITARY elements Theta*g of the Shubnikov group. |
| 117 | + /// Their orbital rotations / return lattices / Ms are appended after the nsym_ unitary |
| 118 | + /// ones, so the raw index isym in [nsym_, nsym_+nanti_) addresses gmatrix_anti[isym-nsym_]. |
| 119 | + int nanti_ = 0; |
| 120 | + /// (nspin=4) true when the configuration carries a non-zero local moment. Then pure time |
| 121 | + /// reversal is NOT a symmetry (it reverses m) and the k-star must be restored with the |
| 122 | + /// Shubnikov elements Theta*gmatrix_anti[] instead of the generic -k shortcut. |
| 123 | + bool magnetic_nspin4_ = false; |
| 124 | + |
| 125 | + double eps_ = 1e-6; |
| 126 | + |
| 127 | + int abfs_Lmax_ = 0; |
| 128 | + |
| 129 | + /// the rotation matrix under the basis of S_l^m. size: [nsym][lmax][nm*nm] |
| 130 | + std::vector<std::vector<ModuleBase::ComplexMatrix>> rotmat_Slm_; |
| 131 | + |
| 132 | + /// The unitary matrix associate D(Rk) with D(k) for each ibz-kpoint Rk and each symmetry operation. |
| 133 | + /// size: [nks_ibz][nsym][nbasis*nbasis], only need to calculate once. |
| 134 | + std::vector<std::map<int, std::vector<std::complex<double>>>> Ms_; |
| 135 | + |
| 136 | + /// (nspin=4) the SU(2) spin-1/2 rotation U(isym) for each symmetry operation, size [nsym]. |
| 137 | + /// The spinor AO rotation is T(isym) (x) U(isym); restore_HR_nspin4 (EXX) uses it to mix |
| 138 | + /// the 4 spin channels of the real-space H(R). Filled in cal_Ms (identity for nspin<4). |
| 139 | + std::vector<SpinRotation::Su2> spin_U_; |
| 140 | + |
| 141 | + /// irreducible sector |
| 142 | + Irreducible_Sector irs_; |
| 143 | + }; |
| 144 | +} |
0 commit comments