29 #include <util/misc/regtime.h>
30 #include <math/mmisc/pairiter.h>
31 #include <chemistry/qc/lcao/utils.h>
32 #include <chemistry/qc/lcao/utils.impl.h>
33 #include <chemistry/qc/mbptr12/r12int_eval.h>
34 #include <util/misc/print.h>
36 #ifndef _chemistry_qc_mbptr12_computetbinttensor_h
37 #define _chemistry_qc_mbptr12_computetbinttensor_h
41 template <
typename DataProcess,
47 const Ref<OrbitalSpace>& space1_bra,
48 const Ref<OrbitalSpace>& space1_ket,
49 const Ref<OrbitalSpace>& space2_bra,
50 const Ref<OrbitalSpace>& space2_ket,
52 const std::vector<std::string>& transform_keys)
55 const bool part1_strong_equiv_part2 = (space1_bra==space2_bra && space1_ket==space2_ket);
56 const bool part1_weak_equiv_part2 = (space1_bra->rank()==space2_bra->rank() && space1_ket->rank()==space2_ket->rank());
58 const bool correct_semantics = (
antisymmetrize && part1_weak_equiv_part2) ||
60 if (!correct_semantics)
61 throw ProgrammingError(
"R12IntEval::compute_tbint_tensor_() -- incorrect call semantics",
65 const bool alphabeta = !(
antisymmetrize && part1_strong_equiv_part2);
67 const bool CorrFactorInBraKet = CorrFactorInBra && CorrFactorInKet;
69 const unsigned int nbrasets = (CorrFactorInBra ? corrfactor()->nfunctions() : 1);
70 const unsigned int nketsets = (CorrFactorInKet ? corrfactor()->nfunctions() : 1);
71 const unsigned int nsets = (CorrFactorInBraKet ? UINT_MAX : nbrasets*nketsets);
74 typedef std::vector< Ref<TwoBodyMOIntsTransform> > tformvec;
75 const size_t num_tforms = transform_keys.size();
76 tformvec transforms(num_tforms);
77 for(
unsigned int t=0; t<num_tforms; ++t) {
78 transforms[t] = moints_runtime4()->get(transform_keys[t]);
81 Timer tim_generic_tensor(
"Generic tensor");
82 std::ostringstream oss;
83 oss <<
"<" << space1_bra->id() <<
" " << space2_bra->id() << (
antisymmetrize ?
"||" :
"|")
84 << space1_ket->id() <<
" " << space2_ket->id() <<
">";
85 const std::string label = oss.str();
87 <<
"Entered generic tensor (" << label <<
") evaluator" << std::endl;
93 Ref<OrbitalSpace> tspace1_bra = transforms[0]->space1();
94 Ref<OrbitalSpace> tspace1_ket = transforms[0]->space2();
95 Ref<OrbitalSpace> tspace2_bra = transforms[0]->space3();
96 Ref<OrbitalSpace> tspace2_ket = transforms[0]->space4();
99 std::vector<unsigned int> map1_bra, map1_ket, map2_bra, map2_ket;
101 std::vector<unsigned int> map12_ket;
103 std::vector<unsigned int> map21_ket;
104 map1_bra = *tspace1_bra<<*space1_bra;
105 map1_ket = *tspace1_ket<<*space1_ket;
106 map2_bra = *tspace2_bra<<*space2_bra;
107 map2_ket = *tspace2_ket<<*space2_ket;
109 if (tspace1_ket == tspace2_ket) {
110 map12_ket = map1_ket;
111 map21_ket = map2_ket;
114 map12_ket = *tspace1_ket<<*space2_ket;
115 map21_ket = *tspace2_ket<<*space1_ket;
119 const unsigned int tblock_ncols = tspace2_ket->rank();
120 const RefDiagSCMatrix evals1_bra = space1_bra->evals();
121 const RefDiagSCMatrix evals1_ket = space1_ket->evals();
122 const RefDiagSCMatrix evals2_bra = space2_bra->evals();
123 const RefDiagSCMatrix evals2_ket = space2_ket->evals();
127 const SpinCase2 S = (alphabeta ? AlphaBeta : AlphaAlpha);
128 SpinMOPairIter iterbra(space1_bra->rank(),space2_bra->rank(),S);
129 SpinMOPairIter iterket(space1_ket->rank(),space2_ket->rank(),S);
131 const unsigned int nbra = iterbra.nij();
133 const unsigned int nket = iterket.nij();
138 Tresult = T.kit()->matrix(
new SCDimension(nbra*nbrasets),
139 new SCDimension(nket*nketsets));
145 unsigned int fbraket = 0;
146 unsigned int fbraoffset = 0;
147 for(
unsigned int fbra=0; fbra<nbrasets; ++fbra,fbraoffset+=nbra) {
149 unsigned int fketoffset = 0;
150 for(
unsigned int fket=0; fket<nketsets; ++fket,fketoffset+=nket,++fbraket) {
152 Ref<TwoBodyMOIntsTransform> tform = transforms[fbraket];
153 const Ref<TwoBodyIntDescr>& intdescr = tform->intdescr();
154 const unsigned int intsetidx = intdescr->intset(tbint_type);
157 ExEnv::out0() << indent <<
"Using transform " << tform->name() << std::endl;
160 Ref<DistArray4> accum = tform->ints_distarray4();
164 std::vector<int> proc_with_ints;
165 const int nproc_with_ints = accum->tasks_with_access(proc_with_ints);
166 const int me =
r12world()->world()->msg()->me();
168 if (accum->has_access(me)) {
169 for(iterbra.start(); iterbra; iterbra.next()) {
170 const int ij = iterbra.ij();
172 const int ij_proc = ij%nproc_with_ints;
173 if (ij_proc != proc_with_ints[me])
176 const unsigned int i = iterbra.i();
177 const unsigned int j = iterbra.j();
178 const unsigned int ii = map1_bra[i];
179 const unsigned int jj = map2_bra[j];
182 ExEnv::outn() << indent <<
"task " << me <<
": working on (i,j) = " << i <<
"," << j <<
" " << std::endl;
183 Timer tim_intsretrieve(
"MO ints retrieve");
184 const double *ij_buf = accum->retrieve_pair_block(ii,jj,intsetidx);
185 tim_intsretrieve.exit();
187 ExEnv::outn() << indent <<
"task " << me <<
": obtained ij blocks" << std::endl;
189 for(iterket.start(); iterket; iterket.next()) {
190 const unsigned int a = iterket.i();
191 const unsigned int b = iterket.j();
192 const unsigned int aa = map1_ket[a];
193 const unsigned int bb = map2_ket[b];
194 const int AB = aa*tblock_ncols+bb;
195 const int ab = iterket.ij();
197 const double I_ijab = ij_buf[AB];
201 ExEnv::out0() <<
"i = " << i <<
" j = " << j <<
" a = " << a <<
" b = " << b
202 <<
" <ij|ab> = " << I_ijab << std::endl;
204 const double T_ijab = DataProcess::I2T(I_ijab,i,j,a,b,evals1_bra,evals1_ket,evals2_bra,evals2_ket);
205 Tresult.accumulate_element(ij+fbraoffset,ab+fketoffset,T_ijab);
208 const int aa = map21_ket[a];
209 const int bb = map12_ket[b];
210 const int BA = bb*tblock_ncols+aa;
211 const double I_ijba = ij_buf[BA];
213 ExEnv::out0() <<
"i = " << i <<
" j = " << j <<
" a = " << a <<
" b = " << b
214 <<
" <ij|ab> = " << I_ijab <<
" <ij|ba> = " << I_ijba << std::endl;
216 const double I_anti = I_ijab - I_ijba;
217 const double T_ijab = DataProcess::I2T(I_anti,i,j,a,b,evals1_bra,evals1_ket,evals2_bra,evals2_ket);
218 Tresult.accumulate_element(ij+fbraoffset,ab+fketoffset,T_ijab);
222 accum->release_pair_block(ii,jj,intsetidx);
227 if (accum->data_persistent()) accum->deactivate();
234 symmetrize<false>(Tresult,Tresult,space1_bra,space1_ket);
240 ExEnv::out0() << indent <<
"Exited generic tensor (" << label <<
") evaluator" << std::endl;
241 tim_generic_tensor.exit();
245 namespace ManyBodyTensors {
253 template <Sign sign = Plus>
256 static double I2T(
double I,
int i1,
int i3,
int i2,
int i4,
270 template <Sign sign = Plus>
273 static double I2T(
double I,
int i1,
int i3,
int i2,
int i4,
279 const double ediff = (- evals1(i1) - evals3(i3) + evals2(i2) + evals4(i4));
288 template <Sign sign = Plus>
291 static double I2T(
double I,
int i1,
int i3,
int i2,
int i4,
297 const double ediff = (- evals1(i1) - evals3(i3) + evals2(i2) + evals4(i4));
308 template <Sign sign = Plus>
311 static double I2T(
double I,
int i1,
int i3,
int i2,
int i4,
317 const double ediff = (- evals1(i1) - evals3(i3) + evals2(i2) + evals4(i4));
319 return I/std::sqrt(std::fabs(ediff));
321 return -I/std::sqrt(std::fabs(ediff));