ABACUS develop
Atomic-orbital Based Ab-initio Computation at UStc
Loading...
Searching...
No Matches
symmetry_rotation_R_hcontainer.hpp
Go to the documentation of this file.
1#include "symmetry_rotation.h"
4namespace ModuleSymmetry
5{
6 template<typename TR>
7 inline void print_global(const TR* tlocal, const int nr, const int nc, const std::string name)
8 {
9 GlobalV::ofs_running << name << std::endl;
10 for (int i = 0;i < nr;++i)
11 {
12 for (int j = 0;j < nc;++j) GlobalV::ofs_running << tlocal[j + i * nc] << " ";
14 }
15 }
16 template<typename TR>
17 inline void print_local(const Parallel_Orbitals& pv, const TR* tlocal, const std::string name)
18 {
19 GlobalV::ofs_running << name << std::endl;
20 for (int i = 0;i < pv.get_row_size();++i)
21 {
22 for (int j = 0;j < pv.get_col_size();++j) GlobalV::ofs_running << tlocal[j + i * pv.get_col_size()] << " ";
24 }
25 }
26 template<typename TR>
27 inline void print_atompair_local(const Parallel_Orbitals& pv, const int iat1, const int iat2, const TR* tlocal, const std::string name)
28 {
29 GlobalV::ofs_running << name << std::endl;
30 for (int i = 0;i < pv.get_row_size(iat1);++i)
31 {
32 for (int j = 0;j < pv.get_col_size(iat2);++j) GlobalV::ofs_running << tlocal[j + i * pv.get_col_size(iat2)] << " ";
34 }
35 }
36
37 template<typename TR> // HContainer type
39 const Symmetry& symm, const Atom* atoms, const Statistics& st, const char mode,
40 const hamilt::HContainer<TR>& HR_irreduceble,
41 hamilt::HContainer<TR>& HR_rotated)const
42 {
43 ModuleBase::TITLE("Symmetry_rotation", "restore_HR");
44 ModuleBase::timer::tick("Symmetry_rotation", "restore_HR");
45 for (auto& apR_isym_irapR : this->irs_.full_map_to_irreducible_sector_)
46 {
47 const Tap& ap = apR_isym_irapR.first.first;
48 const TC& R = apR_isym_irapR.first.second;
49 const int& isym = apR_isym_irapR.second.first;
50 const Tap& irap = apR_isym_irapR.second.second.first;
51 const TC& irR = apR_isym_irapR.second.second.second;
52 assert(irR == this->irs_.rotate_R(symm, isym, ap.first, ap.second, R));
53 // get in and out pointer from HContainer
54 const hamilt::AtomPair<TR>& irap_hc = HR_irreduceble.get_atom_pair(irap.first, irap.second);
55 const int irR_hc = irap_hc.find_R(irR[0], irR[1], irR[2]);
56 if (irR_hc < 0) continue;
57 const TR* irijR_ptr = irap_hc.get_pointer(irR_hc);
58 const hamilt::AtomPair<TR>& ap_hc = HR_rotated.get_atom_pair(ap.first, ap.second);
59 const int R_hc = ap_hc.find_R(R[0], R[1], R[2]);
60 if (R_hc < 0) continue;
61 TR* ijR_ptr = ap_hc.get_pointer(R_hc);
62 rotate_atompair_parallel(irijR_ptr, isym, atoms, st, irap, ap, mode, *irap_hc.get_paraV(), ijR_ptr);
63 }
64 ModuleBase::timer::tick("Symmetry_rotation", "restore_HR");
65 }
66
67 inline void set_block(const int starti, const int startj, const int nr, const ModuleBase::ComplexMatrix& block, double* obj)
68 { // row-major (col-contiguous)
69 for (int i = 0;i < block.nr;++i)
70 for (int j = 0;j < block.nc;++j)
71 obj[starti + i + (startj + j) * nr] = block(j, i).real();
72 };
73 inline void set_block(const int starti, const int startj, const int nr, const ModuleBase::ComplexMatrix& block, std::complex<double>* obj)
74 { // row-major (col-contiguous)
75 for (int i = 0;i < block.nr;++i)
76 for (int j = 0;j < block.nc;++j)
77 obj[starti + i + (startj + j) * nr] = block(j, i);
78 };
79 template<typename TR>
80 void Symmetry_rotation::rotate_atompair_parallel(const TR* Alocal_in, const int isym, const Atom* atoms, const Statistics& st,
81 const Tap& ap_in, const Tap& ap_out, const char mode, const Parallel_Orbitals& pv, TR* Alocal_out, const bool output)const
82 {
83 // all the matrices are row-major (col-contiguous)
84 int iat1 = ap_in.first, iat2 = ap_in.second;
85 int it1 = st.iat2it[iat1], it2 = st.iat2it[iat2];
86 int ia1 = st.iat2ia[iat1], ia2 = st.iat2ia[iat2];
87 // contruct T matrix
88 std::vector<TR> T1, T2;
89 auto set_rotation_matrix = [&](const int& it, const int& ia, std::vector<TR>& T)->int
90 {
91 T.resize(atoms[it].nw * atoms[it].nw, 0.0);
92 const int iwstart = atoms[it].stapos_wf + ia * atoms[it].nw;
93 int iw = 0;
94 while (iw < atoms[it].nw)
95 {
96 int l = atoms[it].iw2l[iw];
97 int nm = 2 * l + 1;
98 // this->set_block_to_mat2d(iwstart, iwstart, this->rotmat_Slm_[isym][l], T_full_2d, pv);
99 set_block(iw, iw, atoms[it].nw, this->rotmat_Slm_[isym][l], T.data());
100 iw += nm;
101 }
102 return iwstart;
103 };
104 int iw1start = set_rotation_matrix(it1, ia1, T1);
105 int iw2start = set_rotation_matrix(it2, ia2, T2);
106
107 // copy Aocal_in to a global atom-pair matrix
108 std::vector<TR> A(atoms[it1].nw * atoms[it2].nw, 0.0);
109
110 int abr1 = pv.atom_begin_row[iat1], abc2 = pv.atom_begin_col[iat2];
111 if (abr1 >= 0 && abc2 >= 0)
112 { // "pv.local2global_row(i) - iw1start": global index in current atom pair
113 for (int j = 0;j < pv.get_col_size(iat2);++j)
114 for (int i = 0;i < pv.get_row_size(iat1);++i)
115 A[(pv.local2global_row(i + abr1) - iw1start) * atoms[it2].nw + (pv.local2global_col(j + abc2) - iw2start)]
116 = Alocal_in[j + i * pv.get_col_size(iat2)];
117 }
118 if (output) print_global(A.data(), atoms[it1].nw, atoms[it2].nw, "A before allreduce");
119 Parallel_Reduce::reduce_all(A.data(), A.size());
120
121 // rotate
122 const char notrans = 'N', transpose = 'T', dagger = 'C';
123 // const std::complex<double> alpha(1.0, 0.0), beta(0.0, 0.0);
124 std::vector<TR> AT2(atoms[it1].nw * atoms[it2].nw, 0.0);
125 std::vector<TR> TAT(atoms[it1].nw * atoms[it2].nw, 0.0);
126 if (mode == 'H')
127 { // H'=T1^\dagger * H * T2
128 BlasConnector::gemm(notrans, notrans, atoms[it1].nw, atoms[it2].nw, atoms[it2].nw,
129 1.0, A.data(), atoms[it2].nw, T2.data(), atoms[it2].nw, 0.0, AT2.data(), atoms[it2].nw);
130 BlasConnector::gemm(dagger, notrans, atoms[it1].nw, atoms[it2].nw, atoms[it1].nw,
131 1.0, T1.data(), atoms[it1].nw, AT2.data(), atoms[it2].nw, 0.0, TAT.data(), atoms[it2].nw);
132 }
133 else if (mode == 'D')
134 { // D' = T1^T * D * T2^* = T1^T * [T2^\dagger * D^T]^T
135 BlasConnector::gemm(dagger, transpose, atoms[it2].nw, atoms[it1].nw, atoms[it2].nw,
136 1.0, T2.data(), atoms[it2].nw, A.data(), atoms[it2].nw, 0.0, AT2.data(), atoms[it1].nw);
137 BlasConnector::gemm(transpose, transpose, atoms[it1].nw, atoms[it2].nw, atoms[it1].nw,
138 1.0, T1.data(), atoms[it1].nw, AT2.data(), atoms[it1].nw, 0.0, TAT.data(), atoms[it2].nw);
139 }
140 else throw std::invalid_argument("Symmetry_rotation::rotate_atompair_tensor: invalid mode.");
141
142 if (output)
143 {
144 print_global(A.data(), atoms[it1].nw, atoms[it2].nw, "A");
145 print_global(T1.data(), atoms[it1].nw, atoms[it1].nw, "T1");
146 print_global(TAT.data(), atoms[it1].nw, atoms[it2].nw, "TAT");
147 print_atompair_local(pv, iat1, iat2, Alocal_out, "Alocal_out");
148 }
149
150 // copy back to Alocal_out
151 iat1 = ap_out.first, iat2 = ap_out.second;
152 it1 = st.iat2it[iat1], it2 = st.iat2it[iat2];
153 ia1 = st.iat2ia[iat1], ia2 = st.iat2ia[iat2];
154 abr1 = pv.atom_begin_row[iat1], abc2 = pv.atom_begin_col[iat2];
155 iw1start = atoms[it1].stapos_wf + ia1 * atoms[it1].nw;
156 iw2start = atoms[it2].stapos_wf + ia2 * atoms[it2].nw;
157 if (abr1 >= 0 && abc2 >= 0)
158 {// ap_in index for TAT but ap_out index for Alocal_out
159 for (int j = 0;j < pv.get_col_size(iat2);++j)
160 for (int i = 0;i < pv.get_row_size(iat1);++i)
161 Alocal_out[j + i * pv.get_col_size(iat2)]
162 = TAT[(pv.local2global_row(i + abr1) - iw1start) * atoms[it2].nw + (pv.local2global_col(j + abc2) - iw2start)];
163 }
164 }
165
166 template<typename TR>
167 void Symmetry_rotation::test_HR_rotation(const Symmetry& symm, const Atom* atoms, const Statistics& st,
168 const char mode, const hamilt::HContainer<TR>& HR_full)
169 {
170 ModuleBase::TITLE("Symmetry_rotation", "test_HR_rotation");
171 auto get_irreducible_ijR_info = [&HR_full, this]() -> std::vector<int>
172 {
173 std::vector<int> irreducible_ijR_info;
174 irreducible_ijR_info.push_back(this->irs_.irreducible_sector_.size());
175 for (auto& irap_irR : this->irs_.irreducible_sector_)
176 {
177 const int iat1 = irap_irR.first.first, iat2 = irap_irR.first.second;
178 irreducible_ijR_info.insert(irreducible_ijR_info.end(), { iat1, iat2, 0 });
179 int nR = 0;
180 for (auto& R : irap_irR.second)
181 if (HR_full.get_atom_pair(iat1, iat2).find_R(R[0], R[1], R[2]) >= 0)
182 {
183 irreducible_ijR_info.insert(irreducible_ijR_info.end(), R.begin(), R.end());
184 ++nR;
185 }
186 irreducible_ijR_info[irreducible_ijR_info.size() - 3 * nR - 1] = nR;
187 }
188 return irreducible_ijR_info;
189 };
190
191 const Parallel_Orbitals* pv = HR_full.get_atom_pair(0, 0).get_paraV();
192 // 1. pick out H(R) in the irreducible sector from full H(R)
193 const std::vector<int>& irreducible_ijR_info = get_irreducible_ijR_info();
194 hamilt::HContainer<TR> HR_irreducible(pv, nullptr, &irreducible_ijR_info);
195 HR_irreducible.set_zero();
196 for (auto& irap_irR : this->irs_.irreducible_sector_)
197 {
198 const int iat1 = irap_irR.first.first, iat2 = irap_irR.first.second;
199 const hamilt::AtomPair<TR>& irap = HR_irreducible.get_atom_pair(iat1, iat2);
200 const hamilt::AtomPair<TR>& ap_full = HR_full.get_atom_pair(iat1, iat2);
201 for (auto& R : irap_irR.second)
202 if (irap.find_R(R[0], R[1], R[2]) >= 0)
203 { // out-of-range R can be added to irreducible sector to be calculated, but not in this test for lack of reference
204 TR* irptr = irap.get_HR_values(R[0], R[1], R[2]).get_pointer();
205 TR* ptr = ap_full.get_HR_values(R[0], R[1], R[2]).get_pointer();
206 std::copy(ptr, ptr + pv->get_row_size(iat1) * pv->get_col_size(iat2), irptr);
207 }
208 }
209
210 //2. rotate
211 hamilt::HContainer<TR> HR_rotated(HR_full);
212 HR_rotated.set_zero();
213 this->restore_HR(symm, atoms, st, mode, HR_irreducible, HR_rotated);
214 //3. compare
215 for (int iat1 = 0;iat1 < st.nat;++iat1)
216 {
217 for (int iat2 = 0;iat2 < st.nat;++iat2)
218 {
219 const hamilt::AtomPair<TR>& ap_full = HR_full.get_atom_pair(iat1, iat2);
220 const hamilt::AtomPair<TR>& ap_rotated = HR_rotated.get_atom_pair(iat1, iat2);
221 assert(ap_full.get_R_size() == ap_rotated.get_R_size());
222 for (int irR = 0;irR < ap_full.get_R_size();++irR)
223 {
224 const TR* full_ptr = ap_full.get_pointer(irR);
225 int* R = ap_full.get_R_index(irR);
226 const TR* rotated_ptr = ap_rotated.get_HR_values(R[0], R[1], R[2]).get_pointer();
227 GlobalV::ofs_running << "atom pair: (" << iat1 << ", " << iat2 << "), R: (" << R[0] << " " << R[1] << " " << R[2] << ")\n";
228 print_atompair_local(*pv, iat1, iat2, rotated_ptr, std::string("R_rot").insert(0, 1, mode));
229 print_atompair_local(*pv, iat1, iat2, full_ptr, std::string("R_ref").insert(0, 1, mode));
230 }
231 }
232 }
233 }
234}
Definition atom_spec.h:7
int nw
Definition atom_spec.h:23
int stapos_wf
Definition atom_spec.h:33
std::vector< int > iw2l
Definition atom_spec.h:20
static void gemm(const char transa, const char transb, const int m, const int n, const int k, const float alpha, const float *a, const int lda, const float *b, const int ldb, const float beta, float *c, const int ldc, base_device::AbacusDevice_t device_type=base_device::AbacusDevice_t::CpuDevice)
Definition blas_connector_matrix.cpp:20
Definition complexmatrix.h:14
int nr
Definition complexmatrix.h:18
matrix real() const
Definition complexmatrix.cpp:265
int nc
Definition complexmatrix.h:19
static void tick(const std::string &class_name_in, const std::string &name_in)
Use twice at a time: the first time, set start_flag to false; the second time, calculate the time dur...
Definition timer.cpp:57
TC rotate_R(const Symmetry &symm, const int isym, const int iat1, const int iat2, const TC &R, const char gauge='R') const
The sub functions to find irreducible sector: {abR}.
Definition irreducible_sector.cpp:5
std::map< Tap, std::set< TC > > irreducible_sector_
whether in 2D plain or not for each symmetry operation
Definition irreducible_sector.h:123
std::map< TapR, std::pair< int, TapR >, apR_less_func > full_map_to_irreducible_sector_
Definition irreducible_sector.h:128
std::vector< std::vector< RI::Tensor< std::complex< double > > > > rotmat_Slm_
the rotation matrix under the basis of S_l^m. size: [nsym][lmax][nm*nm]
Definition symmetry_rotation.h:166
void rotate_atompair_parallel(const TR *Alocal_in, const int isym, const Atom *atoms, const Statistics &st, const Tap &ap_in, const Tap &ap_out, const char mode, const Parallel_Orbitals &pv, TR *Alocal_out, const bool output=false) const
Definition symmetry_rotation_R_hcontainer.hpp:80
std::map< int, std::map< std::pair< int, TC >, RI::Tensor< Tdata > > > restore_HR(const Symmetry &symm, const Atom *atoms, const Statistics &st, const char mode, const std::map< int, std::map< std::pair< int, TC >, RI::Tensor< Tdata > > > &HR_irreduceble) const
Definition symmetry_rotation_R.hpp:40
void test_HR_rotation(const Symmetry &symm, const Atom *atoms, const Statistics &st, const char mode, const std::map< int, std::map< std::pair< int, TC >, RI::Tensor< Tdata > > > &HR_full)
Definition symmetry_rotation_R.hpp:241
RI::Tensor< Tdata > set_rotation_matrix(const Atom &a, const int &isym) const
Definition symmetry_rotation_R.hpp:127
Irreducible_Sector irs_
irreducible sector
Definition symmetry_rotation.h:175
Definition symmetry.h:16
int local2global_col(const int ilc) const
get the global index of a local index (col)
Definition parallel_2d.h:63
int local2global_row(const int ilr) const
get the global index of a local index (row)
Definition parallel_2d.h:57
Definition parallel_orbitals.h:9
int get_col_size() const
dimension getters for 2D-block-cyclic division of Hamiltonian matrix get_col_size() : total number of...
Definition parallel_orbitals.h:76
int get_row_size() const
Definition parallel_orbitals.h:77
std::vector< int > atom_begin_col
Definition parallel_orbitals.h:100
std::vector< int > atom_begin_row
Definition parallel_orbitals.h:99
Definition atom_pair.h:42
BaseMatrix< T > & get_HR_values(int rx_in, int ry_in, int rz_in)
get target BaseMatrix of target cell for const AtomPair, it will return a const BaseMatrix<T> object,...
Definition atom_pair.cpp:393
T * get_pointer(int ir=-1) const
get pointer of value from a submatrix
Definition atom_pair.cpp:844
const Parallel_Orbitals * get_paraV() const
get Parallel_Orbitals pointer of this AtomPair for checking 2d-block parallel
Definition atom_pair.cpp:358
ModuleBase::Vector3< int > get_R_index(const int &index) const
Definition atom_pair.cpp:795
size_t get_R_size() const
Definition atom_pair.h:288
int find_R(const int &rx_in, const int &ry_in, const int &rz_in) const
Definition atom_pair.cpp:441
Definition hcontainer.h:144
void set_zero()
set values of all <IJR> matrix to zero
Definition hcontainer.cpp:210
AtomPair< T > & get_atom_pair(int i, int j) const
return a reference of AtomPair with index of atom I and J in atom_pairs
Definition hcontainer.cpp:353
Definition output.h:13
#define T
Definition exp.cpp:237
std::ofstream ofs_running
Definition global_variable.cpp:38
void TITLE(const std::string &class_name, const std::string &function_name, const bool disable)
Definition tool_title.cpp:18
Definition symm_other.cpp:4
void print_local(const Parallel_Orbitals &pv, const TR *tlocal, const std::string name)
Definition symmetry_rotation_R_hcontainer.hpp:17
void set_block(const int starti, const int startj, const RI::Tensor< std::complex< double > > &block, RI::Tensor< Tdata > &obj_tensor)
Definition symmetry_rotation_R.hpp:116
void print_global(const TR *tlocal, const int nr, const int nc, const std::string name)
Definition symmetry_rotation_R_hcontainer.hpp:7
std::array< int, 3 > TC
Definition irreducible_sector.h:14
void print_atompair_local(const Parallel_Orbitals &pv, const int iat1, const int iat2, const TR *tlocal, const std::string name)
Definition symmetry_rotation_R_hcontainer.hpp:27
std::pair< int, int > Tap
Definition irreducible_sector.h:13
void reduce_all(T &object)
reduce in all process
Definition depend_mock.cpp:14
usefull data and index maps
Definition unitcell_data.h:47
int nat
Definition unitcell_data.h:49
int * iat2it
Definition unitcell_data.h:50
int * iat2ia
Definition unitcell_data.h:51