ABACUS develop
Atomic-orbital Based Ab-initio Computation at UStc
Loading...
Searching...
No Matches
symmetry_rotation_R.hpp
Go to the documentation of this file.
1#include "symmetry_rotation.h"
3#include "source_base/timer.h"
4#include <array>
5#include <RI/global/Global_Func-2.h>
6#include <RI/physics/symmetry/Symmetry_Rotation.h>
7namespace ModuleSymmetry
8{
9 template<typename Tdata>
10 inline void print_tensor(const RI::Tensor<Tdata>& t, const std::string& name, const double& threshold = 0.0)
11 {
12 GlobalV::ofs_running << name << ":\n";
13 for (int i = 0;i < t.shape[0];++i)
14 {
15 for (int j = 0;j < t.shape[1];++j) {
16 GlobalV::ofs_running << ((std::abs(t(i, j)) > threshold) ? t(i, j) : static_cast<Tdata>(0)) << " ";
17}
18 GlobalV::ofs_running << std::endl;
19 }
20 }
21 template<typename Tdata>
22 inline void print_tensor3(const RI::Tensor<Tdata>& t, const std::string& name, const double& threshold = 0.0)
23 {
24 GlobalV::ofs_running << name << ":\n";
25 for (int a = 0;a < t.shape[0];++a)
26 {
27 GlobalV::ofs_running << "abf: " << a << '\n';
28 for (int i = 0;i < t.shape[1];++i)
29 {
30 for (int j = 0;j < t.shape[2];++j) {
31 GlobalV::ofs_running << ((std::abs(t(a, i, j)) > threshold) ? t(a, i, j) : static_cast<Tdata>(0)) << " ";
32}
33 GlobalV::ofs_running << std::endl;
34 }
35 GlobalV::ofs_running << std::endl;
36 }
37 }
38
39 template<typename Tdata>
40 std::map<int, std::map<std::pair<int, TC>, RI::Tensor<Tdata>>> Symmetry_rotation::restore_HR(
41 const Symmetry& symm, const Atom* atoms, const Statistics& st, const char mode,
42 const std::map<int, std::map<std::pair<int, TC>, RI::Tensor<Tdata>>>& HR_irreducible) const
43 {
44 ModuleBase::TITLE("Symmetry_rotation", "restore_HR");
45 ModuleBase::timer::tick("Symmetry_rotation", "restore_HR");
46 std::map<int, std::map<std::pair<int, TC>, RI::Tensor<Tdata>>> HR_full;
47 // irreducile-to-full map ver.
48 for (auto& tmp1 : HR_irreducible)
49 {
50 const int& irap1 = tmp1.first;
51 for (auto& tmp2 : tmp1.second)
52 {
53 const int& irap2 = tmp2.first.first;
54 const Tap& irap = { irap1, irap2 };
55 const TC& irR = tmp2.first.second;
56 const TapR& irapR = { irap, irR };
57 if (this->irs_.sector_stars_.find(irapR) != this->irs_.sector_stars_.end())
58 {
59 for (auto& isym_apR : this->irs_.sector_stars_.at(irapR))
60 {
61 const int& isym = isym_apR.first;
62 const TapR& apR = isym_apR.second;
63 const int& ap1 = apR.first.first;
64 const int& ap2 = apR.first.second;
65 const TC& R = apR.second;
66 HR_full[ap1][{ap2, R}] = rotate_atompair_serial(tmp2.second, isym, atoms[st.iat2it[irap1]], atoms[st.iat2it[irap2]], mode);
67 }
68 }
69 else { std::cout << "Warning: not found: irreducible atom pair =(" << irap1 << "," << irap2 << "), irR=(" << irR[0] << "," << irR[1] << "," << irR[2] << ")\n";}
70 }
71 }
72 // full-to-irreducible map ver. (problematic in parallel)
73 // openmp slows down this for loop, why?
74 // for (auto& apR_isym_irapR : this->irs_.full_map_to_irreducible_sector_)
75 // {
76 // const Tap& ap = apR_isym_irapR.first.first;
77 // const TC& R = apR_isym_irapR.first.second;
78 // const int& isym = apR_isym_irapR.second.first;
79 // const Tap& irap = apR_isym_irapR.second.second.first;
80 // const TC& irR = apR_isym_irapR.second.second.second;
81 // // rotate the matrix and pack data
82 // // H_12(R)=T^\dagger(V)H_1'2'(VR+O_1-O_2)T(V)
83 // if (HR_irreducible.find(irap.first) != HR_irreducible.end() && HR_irreducible.at(irap.first).find({ irap.second, irR }) != HR_irreducible.at(irap.first).end())
84 // HR_full[ap.first][{ap.second, R}] = rotate_atompair_serial(HR_irreducible.at(irap.first).at({ irap.second, irR }),
85 // isym, atoms[st.iat2it[irap.first]], atoms[st.iat2it[irap.second]], mode);
86 // else
87 // std::cout << "not found: current atom pair =(" << ap.first << "," << ap.second << "), R=(" << R[0] << "," << R[1] << "," << R[2] << "), irreducible atom pair =(" << irap.first << "," << irap.second << "), irR=(" << irR[0] << "," << irR[1] << "," << irR[2] << ")\n";
88 // }
89 // // test: output HR_irreducile
90 // for (auto& tmp1 : HR_irreducible)
91 // {
92 // const int& a1 = tmp1.first;
93 // for (auto& tmp2 : tmp1.second)
94 // {
95 // const int& a2 = tmp2.first.first;
96 // const TC& R = tmp2.first.second;
97 // print_tensor(tmp2.second, "HR_irreducible (" + std::to_string(a1) + ", " + std::to_string(a2) + "), R=(" + std::to_string(R[0]) + " " + std::to_string(R[1]) + " " + std::to_string(R[2]) + ")");
98 // }
99 // }
100 // // test: output HR
101 // for (auto& tmp1 : HR_full)
102 // {
103 // const int& a1 = tmp1.first;
104 // for (auto& tmp2 : tmp1.second)
105 // {
106 // const int& a2 = tmp2.first.first;
107 // const TC& R = tmp2.first.second;
108 // print_tensor(tmp2.second, "HR_full (" + std::to_string(a1) + ", " + std::to_string(a2) + "), R=(" + std::to_string(R[0]) + " " + std::to_string(R[1]) + " " + std::to_string(R[2]) + ")");
109 // }
110 // }
111 ModuleBase::timer::tick("Symmetry_rotation", "restore_HR");
112 return HR_full;
113 }
114
115 template<typename Tdata>
116 inline void set_block(const int starti, const int startj, const RI::Tensor<std::complex<double>>& block,
117 RI::Tensor<Tdata>& obj_tensor)
118 { // no changing row/col order
119 for (int i = 0;i < block.shape[0];++i) {
120 for (int j = 0;j < block.shape[1];++j) {
121 obj_tensor(starti + i, startj + j) = RI::Global_Func::convert<Tdata>(block(i, j));
122}
123}
124 }
125
126 template<typename Tdata>
127 RI::Tensor<Tdata> Symmetry_rotation::set_rotation_matrix(const Atom& a, const int& isym)const
128 {
129 RI::Tensor<Tdata> T({ static_cast<size_t>(a.nw), static_cast<size_t>(a.nw) }); // check if zero
130 int iw = 0;
131 while (iw < a.nw)
132 {
133 int l = a.iw2l[iw];
134 int nm = 2 * l + 1;
135 set_block(iw, iw, this->rotmat_Slm_[isym][l], T);
136 iw += nm;
137 }
138 return T;
139 }
140 template<typename Tdata>
141 RI::Tensor<Tdata> Symmetry_rotation::rotate_atompair_serial(const RI::Tensor<Tdata>& A, const int isym,
142 const Atom& a1, const Atom& a2, const char mode, const bool output)const
143 { // due to col-contiguous, actually what we know is T^T and H^T (or D^T),
144 // and what we calculate is(H'^T = T ^ T * H ^ T * T^*) or (D'^T = T ^ \dagger * D ^ T * T)
145 assert(mode == 'H' || mode == 'D');
146 bool sametype = (a1.label == a2.label);
147 assert(A.shape[0] == a1.nw);//col
148 assert(A.shape[1] == a2.nw);//row
149 // contrut T matrix
150 const RI::Tensor<Tdata>& T1 = this->set_rotation_matrix<Tdata>(a1, isym);
151 const RI::Tensor<Tdata>& T2 = sametype ? T1 : this->set_rotation_matrix<Tdata>(a2, isym);
152 // rotate
153 RI::Tensor<Tdata>TAT(A.shape);
154 (mode == 'H') ? RI::Sym::T1_HR_T2(TAT.ptr(), A.ptr(), T1, T2) : RI::Sym::T1_DR_T2(TAT.ptr(), A.ptr(), T1, T2);
155 if (output)
156 {
157 print_tensor(A, "A");
158 print_tensor(T1, "T1");
159 print_tensor(T2, "T2");
160 print_tensor(TAT, "TAT");
161 }
162 return TAT;
163 }
164 template<typename Tdata>
165 void Symmetry_rotation::rotate_atompair_serial(Tdata* TAT, const Tdata* A,
166 const int& nw1, const int& nw2, const int isym,
167 const Atom& a1, const Atom& a2, const char mode)const
168 { // due to col-contiguous, actually what we know is T^T and H^T (or D^T),
169 // and what we calculate is(H'^T = T ^ T * H ^ T * T^*) or (D'^T = T ^ \dagger * D ^ T * T)
170 assert(mode == 'H' || mode == 'D');
171 bool sametype = (a1.label == a2.label);
172 assert(nw1 == a1.nw);//col
173 assert(nw2 == a2.nw);//row
174 // contrut T matrix
175 const RI::Tensor<Tdata>& T1 = this->set_rotation_matrix<Tdata>(a1, isym);
176 const RI::Tensor<Tdata>& T2 = sametype ? T1 : this->set_rotation_matrix<Tdata>(a2, isym);
177 // rotate
178 (mode == 'H') ? RI::Sym::T1_HR_T2(TAT, A, T1, T2) : RI::Sym::T1_DR_T2(TAT, A, T1, T2);
179 }
180
181
182 template<typename Tdata>
183 RI::Tensor<Tdata> Symmetry_rotation::set_rotation_matrix_abf(const int& type, const int& isym)const
184 {
185 int nabfs = 0;
186 for (int l = 0;l < this->abfs_l_nchi_[type].size();++l) {nabfs += this->abfs_l_nchi_[type][l] * (2 * l + 1);
187}
188 RI::Tensor<Tdata> T({ static_cast<size_t>(nabfs), static_cast<size_t>(nabfs) }); // check if zero
189 int iw = 0;
190 for (int L = 0;L < this->abfs_l_nchi_[type].size();++L)
191 {
192 int nm = 2 * L + 1;
193 for (int N = 0;N < this->abfs_l_nchi_[type][L];++N)
194 {
195 set_block(iw, iw, this->rotmat_Slm_[isym][L], T);
196 iw += nm;
197 // std::cout << "L=" << L << ", N=" << N << ", iw=" << iw << "\n";
198 }
199 }
200 assert(iw == nabfs);
201 return T;
202 }
203
204 template<typename Tdata>
205 RI::Tensor<Tdata> Symmetry_rotation::rotate_singleC_serial(const RI::Tensor<Tdata>& C,
206 const int isym, const Atom& a1, const Atom& a2, const int& type1, bool output)const
207 {
208 assert(this->reduce_Cs_);
209 RI::Tensor<Tdata> Cout(C.shape);
210 assert(C.shape.size() == 3);
211 const int& slice_size = C.shape[1] * C.shape[2];
212 // step 1: multiply 2 AOs' rotation matrices
213 for (int iabf = 0;iabf < C.shape[0];++iabf) {
214 this->rotate_atompair_serial(Cout.ptr() + iabf * slice_size, C.ptr() + iabf * slice_size,
215 a1.nw, a2.nw, isym, a1, a2, 'H');
216}
217 // step 2: multiply the ABFs' rotation matrix from the left
218 const RI::Tensor<Tdata>& Tabfs = this->set_rotation_matrix_abf<Tdata>(type1, isym);
219 RI::Sym::T1_HR(Cout.ptr(), Cout.ptr(), Tabfs, slice_size);
220 return Cout;
221 }
222
223 template<typename Tdata>
224 void Symmetry_rotation::print_HR(const std::map<int, std::map<std::pair<int, TC>, RI::Tensor<Tdata>>>& HR, const std::string name, const double& threshold)
225 {
226 for (auto& HR_ia1 : HR)
227 {
228 int iat1 = HR_ia1.first;
229 for (auto& HR_ia12R : HR_ia1.second)
230 {
231 int iat2 = HR_ia12R.first.first;
232 TC R = HR_ia12R.first.second;
233 const RI::Tensor<Tdata>& HR_tensor = HR_ia12R.second;
234 std::cout << "atom pair (" << iat1 << ", " << iat2 << "), R=(" << R[0] << "," << R[1] << "," << R[2] << "), ";
235 print_tensor(HR_tensor, name, threshold);
236 }
237 }
238 }
239
240 template<typename Tdata>
241 void Symmetry_rotation::test_HR_rotation(const Symmetry& symm, const Atom* atoms, const Statistics& st, const char mode,
242 const std::map<int, std::map<std::pair<int, TC>, RI::Tensor<Tdata>>>& HR_full)
243 {
244 ModuleBase::TITLE("Symmetry_rotation", "test_HR_rotation");
245
246 // 1. pick out H(R) in the irreducible sector from full H(R)
247 std::map<int, std::map<std::pair<int, TC>, RI::Tensor<Tdata>>> HR_irreducible;
248 for (auto& irap_Rs : this->irs_.irreducible_sector_)
249 {
250 const Tap& irap = irap_Rs.first;
251 for (auto& irR : irap_Rs.second)
252 {
253 const std::pair<int, TC> a2_irR = { irap.second, irR };
254 HR_irreducible[irap.first][a2_irR] = (HR_full.at(irap.first).count(a2_irR) != 0) ?
255 HR_full.at(irap.first).at(a2_irR)
256 : RI::Tensor<Tdata>(HR_full.at(irap.first).begin()->second.shape);
257 }
258 }
259 // 2. rotate
260 std::map<int, std::map<std::pair<int, TC>, RI::Tensor<Tdata>>> HR_rotated = restore_HR(symm, atoms, st, mode, HR_irreducible);
261 // 3. compare
262 for (auto& HR_ia1 : HR_rotated)
263 {
264 int iat1 = HR_ia1.first;
265 for (auto& HR_ia12R : HR_ia1.second)
266 {
267 int iat2 = HR_ia12R.first.first;
268 TC R = HR_ia12R.first.second;
269 const RI::Tensor<Tdata>& HR_rot = HR_ia12R.second;
270 if (HR_full.at(iat1).count({ iat2, R }) == 0)// rot back but not found
271 {
272 std::cout << "R_rot not found in atom pair (" << iat1 << ", " << iat2 << "): R=(" << R[0] << "," << R[1] << "," << R[2] << "):\n";
273 continue;
274 }
275 const RI::Tensor<Tdata>& HR_ref = HR_full.at(iat1).at({ iat2, R });
276 assert(HR_rot.shape[0] == HR_ref.shape[0]);
277 assert(HR_rot.shape[1] == HR_ref.shape[1]);
278 // output
279 std::cout << "atom pair (" << iat1 << ", " << iat2 << "), R=(" << R[0] << "," << R[1] << "," << R[2] << "):\n";
280 print_tensor(HR_rot, std::string("R_rot").insert(0, 1, mode));
281 print_tensor(HR_ref, std::string("R_ref").insert(0, 1, mode));
282 }
283 }
284 }
285
286 template<typename Tdata>
287 void Symmetry_rotation::test_Cs_rotation(const Symmetry& symm, const Atom* atoms, const Statistics& st,
288 const std::map<int, std::map<std::pair<int, TC>, RI::Tensor<Tdata>>>& Cs_full)const
289 {
290 for (auto& sector_pair : this->irs_.full_map_to_irreducible_sector_)
291 {
292 const TapR& apR = sector_pair.first;
293 const int& isym = sector_pair.second.first;
294 const TapR& irapR = sector_pair.second.second;
295 // if (apR.first != irapR.first || apR.second != irapR.second)
296 if (apR.first != irapR.first)
297 {
298 std::cout << "irapR=(" << irapR.first.first << "," << irapR.first.second << "), (" << irapR.second[0] << "," << irapR.second[1] << "," << irapR.second[2] << "):\n";
299 std::cout << "apR=(" << apR.first.first << "," << apR.first.second << "), (" << apR.second[0] << "," << apR.second[1] << "," << apR.second[2] << "):\n";
300 const RI::Tensor<Tdata>& Cs_ir = Cs_full.at(irapR.first.first).at({ irapR.first.second,irapR.second });
301 const RI::Tensor<Tdata>& Cs_ref = Cs_full.at(apR.first.first).at({ apR.first.second,apR.second });
302 const RI::Tensor<Tdata>& Cs_rot = this->rotate_singleC_serial(Cs_ir, isym,
303 atoms[st.iat2it[irapR.first.first]], atoms[st.iat2it[irapR.first.second]], irapR.first.first);
304 print_tensor3(Cs_rot, "Cs_rot");
305 print_tensor3(Cs_ref, "Cs_ref");
306 print_tensor3(Cs_ir, "Cs_irreducible");
307 exit(0);
308 }
309 }
310
311 }
312
313}
Definition atom_spec.h:7
int nw
Definition atom_spec.h:23
std::string label
Definition atom_spec.h:35
std::vector< int > iw2l
Definition atom_spec.h:20
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
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::map< int, TapR > > sector_stars_
Definition irreducible_sector.h:132
std::map< TapR, std::pair< int, TapR >, apR_less_func > full_map_to_irreducible_sector_
Definition irreducible_sector.h:128
bool reduce_Cs_
Definition symmetry_rotation.h:160
void test_Cs_rotation(const Symmetry &symm, const Atom *atoms, const Statistics &st, const std::map< int, std::map< std::pair< int, TC >, RI::Tensor< Tdata > > > &Cs_full) const
Definition symmetry_rotation_R.hpp:287
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
std::vector< std::vector< int > > abfs_l_nchi_
number of abfs for each angular momentum
Definition symmetry_rotation.h:163
RI::Tensor< Tdata > rotate_atompair_serial(const RI::Tensor< Tdata > &A, const int isym, const Atom &a1, const Atom &a2, const char mode, bool output=false) const
Definition symmetry_rotation_R.hpp:141
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
RI::Tensor< Tdata > set_rotation_matrix_abf(const int &type, const int &isym) const
Definition symmetry_rotation_R.hpp:183
void print_HR(const std::map< int, std::map< std::pair< int, TC >, RI::Tensor< Tdata > > > &HR, const std::string name, const double &threshold=0.0)
Definition symmetry_rotation_R.hpp:224
RI::Tensor< Tdata > rotate_singleC_serial(const RI::Tensor< Tdata > &C, const int isym, const Atom &a1, const Atom &a2, const int &type1, bool output=false) const
rotate a 3-dim C tensor in RI technique
Definition symmetry_rotation_R.hpp:205
Irreducible_Sector irs_
irreducible sector
Definition symmetry_rotation.h:175
Definition symmetry.h:16
Definition output.h:13
#define N
Definition exp.cpp:24
#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
std::pair< Tap, TC > TapR
Definition irreducible_sector.h:15
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
std::array< int, 3 > TC
Definition irreducible_sector.h:14
void print_tensor(const RI::Tensor< Tdata > &t, const std::string &name, const double &threshold=0.0)
Definition symmetry_rotation_R.hpp:10
std::pair< int, int > Tap
Definition irreducible_sector.h:13
void print_tensor3(const RI::Tensor< Tdata > &t, const std::string &name, const double &threshold=0.0)
Definition symmetry_rotation_R.hpp:22
#define threshold
Definition sph_bessel_recursive_test.cpp:4
usefull data and index maps
Definition unitcell_data.h:47
int * iat2it
Definition unitcell_data.h:50