28 #ifndef _chemistry_qc_mbptr12_contract_tbint_tensors_to_obtensor_h
29 #define _chemistry_qc_mbptr12_contract_tbint_tensors_to_obtensor_h
32 #include <math/mmisc/pairiter.h>
33 #include <chemistry/qc/lcao/utils.h>
34 #include <chemistry/qc/lcao/utils.impl.h>
35 #include <chemistry/qc/mbptr12/r12int_eval.h>
36 #include <util/misc/print.h>
41 template <
typename DataProcess_Bra,
42 typename DataProcess_Ket,
60 const std::vector<std::string>& tformkeys_bra,
61 const std::vector<std::string>& tformkeys_ket) {
63 bool r12coeffs_bra = (tbtensor_type_bra.twobodytensor_type()==TwoBodyTensorInfo::geminalcoeff) ?
true :
false;
64 bool r12coeffs_ket = (tbtensor_type_ket.twobodytensor_type()==TwoBodyTensorInfo::geminalcoeff) ?
true :
false;
66 TwoBodyOper::type tbint_type_bra = (r12coeffs_bra) ? corrfactor()->tbint_type_eri()
67 : tbtensor_type_bra.twobodyint_type();
68 TwoBodyOper::type tbint_type_ket = (r12coeffs_ket) ? corrfactor()->tbint_type_eri()
69 : tbtensor_type_ket.twobodyint_type();
72 const bool part1_strong_equiv_part2 = (space1_bra==space2_intb &&
73 space1_ket==space2_intk);
76 const bool part1_weak_equiv_part2 =
false;
78 bool correct_semantics = ( (space1_intb->rank() == space1_intk->rank()) &&
79 (space2_intb->rank() == space2_intk->rank()) &&
80 (space3_intb->rank() == space3_intk->rank()) );
83 correct_semantics = ( correct_semantics &&
84 (tpcontract->nrow() == space2_intb->rank()) &&
85 (tpcontract->ncol() == space3_intb->rank()) );
87 if (!correct_semantics)
88 throw ProgrammingError(
"R12IntEval::contract_tbint_tensor_() -- incorrect call semantics",
92 const bool part1_intequiv_part2 = (space2_intb==space3_intb &&
93 space2_intk==space3_intk);
95 const bool alphabeta = !(part1_strong_equiv_part2 &&
96 part1_intequiv_part2);
102 const SpinCase2 S = pairspin;
106 const bool CorrFactorInBraInt = CorrFactorInBra && CorrFactorInInt;
107 const bool CorrFactorInKetInt = CorrFactorInKet && CorrFactorInInt;
109 const unsigned int nbrasets = (CorrFactorInBra ? corrfactor()->nfunctions() : 1);
110 const unsigned int nketsets = (CorrFactorInKet ? corrfactor()->nfunctions() : 1);
111 const unsigned int nintsets = (CorrFactorInInt ? corrfactor()->nfunctions() : 1);
112 const unsigned int nbraintsets = (CorrFactorInBraInt ? UINT_MAX : nbrasets*nintsets);
113 const unsigned int nketintsets = (CorrFactorInKetInt ? UINT_MAX : nketsets*nintsets);
119 typedef std::vector<Ref<TwoBodyMOIntsTransform> > tformvec;
122 const size_t num_tforms_bra = tformkeys_bra.size();
123 tformvec transforms_bra(num_tforms_bra);
124 for (
unsigned int t = 0; t < num_tforms_bra; ++t) {
125 transforms_bra[t] = moints_runtime4()->get(tformkeys_bra[t]);
129 const size_t num_tforms_ket = tformkeys_ket.size();
130 tformvec transforms_ket(num_tforms_ket);
131 for (
unsigned int t = 0; t < num_tforms_ket; ++t) {
132 transforms_ket[t] = moints_runtime4()->get(tformkeys_ket[t]);
138 Timer timer(
"Generic tensor contract");
141 std::ostringstream oss_bra;
142 oss_bra <<
"<" << space1_bra->id() <<
" " << space1_intb->id() << (
antisymmetrize ?
"||" :
"|")
143 << space2_intb->id() <<
" " << space3_intb->id() <<
">";
144 const std::string label_bra = oss_bra.str();
145 std::ostringstream oss_ket;
146 oss_ket <<
"<" << space1_ket->id() <<
" " << space1_intk->id() << (
antisymmetrize ?
"||" :
"|")
147 << space2_intk->id() <<
" " << space3_intk->id() <<
">";
148 const std::string label_ket = oss_ket.str();
149 std::ostringstream oss;
151 << space1_ket->id() <<
"> = "
152 << label_bra <<
" . " << label_ket <<
"^T";
156 <<
"Entered generic contraction (" << label <<
")" << std::endl;
173 std::vector<unsigned int> map1_bra, map1_ket,
174 map1_intb, map2_intb, map3_intb, map1_intk, map2_intk, map3_intk;
176 std::vector<unsigned int> map23_intb;
178 std::vector<unsigned int> map32_intb;
180 std::vector<unsigned int> map23_intk;
182 std::vector<unsigned int> map32_intk;
185 map1_bra = *tspace1_bra<<*space1_bra;
186 map1_intb = *tspace1_intb<<*space1_intb;
187 map2_intb = *tspace2_intb<<*space2_intb;
188 map3_intb = *tspace3_intb<<*space3_intb;
191 if (tspace2_intb == tspace3_intb) {
192 map23_intb = map2_intb;
193 map32_intb = map3_intb;
196 map23_intb = *tspace2_intb<<*space3_intb;
197 map32_intb = *tspace3_intb<<*space2_intb;
203 map1_ket = *tspace1_ket<<*space1_ket;
204 map1_intk = *tspace1_intk<<*space1_intk;
205 map2_intk = *tspace2_intk<<*space2_intk;
206 map3_intk = *tspace3_intk<<*space3_intk;
209 if (tspace2_intk == tspace3_intk) {
210 map23_intk = map2_intk;
211 map32_intk = map3_intk;
214 map23_intk = *tspace2_intk<<*space3_intk;
215 map32_intk = *tspace3_intk<<*space2_intk;
220 const unsigned int bratform_block_ncols = tspace3_intb->rank();
221 const unsigned int kettform_block_ncols = tspace3_intk->rank();
231 SpinMOPairIter iterint(space2_intb->rank(),(alphabeta ? space3_intb : space2_intb)->rank(),S);
233 const unsigned int nint = iterint.
nij();
236 const unsigned int nbra = space1_bra_dim->n();
237 const unsigned int nket = space1_ket_dim->n();
240 const unsigned int blksize_int = space2_intb->rank() * space3_intb->rank();
241 double* T_alphap =
new double[blksize_int];
242 double* T_qp =
new double[blksize_int];
245 int nmo_space1_bra = space1_bra->rank();
246 int nmo_space1_intb = space1_intb->rank();
247 int nmo_space1_ket = space1_ket->rank();
248 int nmo_space1_intk = space1_intk->rank();
251 for(
unsigned int fint=0; fint<nintsets; ++fint) {
252 unsigned int fbraoffset = 0;
253 for(
unsigned int fbra=0; fbra<nbrasets; ++fbra,fbraoffset+=nbra) {
254 const unsigned int fbraint = fbra*nintsets+fint;
257 const unsigned int intsetidx_bra = intdescrb->intset(tbint_type_bra);
263 accumb = tformb->ints_distarray4();
267 unsigned int fketoffset = 0;
268 for(
unsigned int fket=0; fket<nketsets; ++fket,fketoffset+=nket) {
269 const unsigned int fketint = fket*nintsets+fint;
272 const unsigned int intsetidx_ket = intdescrk->intset(tbint_type_ket);
277 accumk = tformk->ints_distarray4();
283 << tformb->name() <<
" and "
284 << tformk->name() << std::endl;
289 std::vector<int> proc_with_ints;
290 const int nproc_with_ints = accumb->tasks_with_access(proc_with_ints);
291 const int me =
r12world()->world()->msg()->me();
292 const bool nket_ge_nevals = (nket >= nproc_with_ints);
294 Timer tim_mo_ints_retrieve;
295 tim_mo_ints_retrieve.
set_default(
"MO ints retrieve");
296 if (accumb->has_access(me)) {
297 unsigned int alphapq = 0;
298 for(
unsigned int alpha=0; alpha<nmo_space1_bra; alpha++) {
299 for(
unsigned int p=0; p<nmo_space1_intb; p++) {
300 unsigned int alphap = alpha*nmo_space1_intb + p;
301 bool fetch_alphap_block =
false;
302 if (nket_ge_nevals) {
303 fetch_alphap_block =
true;
306 const int first_alphap_task = alphapq%nproc_with_ints;
307 const int last_alphap_task = (alphapq+nket-1)%nproc_with_ints;
309 if ( !(first_alphap_task > proc_with_ints[me] && proc_with_ints[me] > last_alphap_task) )
310 fetch_alphap_block =
true;
312 if(!fetch_alphap_block)
315 const unsigned int alphaalpha = map1_bra[alpha];
316 const unsigned int pp = map1_intb[p];
318 const double *alphap_buf;
320 tim_mo_ints_retrieve.enter_default();
321 alphap_buf = accumb->retrieve_pair_block(alphaalpha,pp,intsetidx_bra);
322 tim_mo_ints_retrieve.exit_default();
326 ExEnv::outn() << indent <<
"task " << me <<
": obtained alphap blocks" << std::endl;
328 for(
unsigned int q=0; q<nmo_space1_ket; q++) {
329 unsigned int pq = p*nmo_space1_ket + q;
330 const int alphapq_proc = alphapq%nproc_with_ints;
331 if(pairspin==AlphaBeta) {
332 if (alphapq_proc != proc_with_ints[me])
334 const unsigned int qq = map1_ket[q];
337 ExEnv::outn() << indent <<
"task " << me <<
": working on <alpha,p | q,p> = <"
338 << alpha <<
"," << p <<
" | " << q <<
"," << p <<
">" << std::endl;
340 const double *qp_buf;
342 tim_mo_ints_retrieve.enter_default();
343 qp_buf = accumk->retrieve_pair_block(qq,pp,intsetidx_ket);
344 tim_mo_ints_retrieve.exit_default();
348 ExEnv::outn() << indent <<
"task " << me <<
": obtained qp blocks" << std::endl;
351 memset(T_alphap, 0, blksize_int*
sizeof(
double));
352 memset(T_qp, 0, blksize_int*
sizeof(
double));
355 ExEnv::out0() << indent <<
"alpha = " << alpha <<
" p = " << p <<
" q = " << q
356 << incindent << std::endl;
359 for(iterint.start(); iterint; iterint.next()) {
360 unsigned int r = iterint.i();
361 unsigned int s = iterint.j();
362 unsigned int rs = iterint.ij();
366 const unsigned int rr = map2_intb[r];
367 const unsigned int ss = map3_intb[s];
368 RS_bra = rr*bratform_block_ncols + ss;
371 const unsigned int rr = map2_intk[r];
372 const unsigned int ss = map3_intk[s];
373 RS_ket = rr*kettform_block_ncols + ss;
377 I_alphaprs = alphap_buf[RS_bra];
384 I_qprs = qp_buf[RS_ket];
391 ExEnv::out0() << indent <<
" r = " << r <<
" s = " << s << std::endl;
395 ExEnv::out0() << indent <<
" <alphap|rs> = " << I_alphaprs << std::endl
396 << indent <<
" <qp|rs> = " << I_qprs << std::endl;
401 T_alphaprs = DataProcess_Bra::I2T(I_alphaprs,alpha,p,r,s,
402 evals1_bra,evals2_intb,evals1_intb,evals3_intb);
405 T_alphaprs = I_alphaprs;
410 T_qprs = DataProcess_Ket::I2T(I_qprs,q,p,r,s,
411 evals1_ket,evals2_intk,evals1_intk,evals3_intk);
418 ExEnv::out0() << indent <<
" <alphap|T|rs> = " << T_alphaprs << std::endl
419 << indent <<
" <qp|T|rs> = " << T_qprs << std::endl;
422 T_alphap[rs] = T_alphaprs;
428 double T_alphapqp = tpcontract->contract(T_alphap,T_qp);
433 <<
" <alphap|qp> = " << T_alphapqp << std::endl;
436 T.accumulate_element(alpha,q,T_alphapqp);
439 accumk->release_pair_block(qq,pp,intsetidx_ket);
446 if (alphapq_proc != proc_with_ints[me])
448 const unsigned int qq = map1_ket[q];
451 ExEnv::outn() << indent <<
"task " << me <<
": working on <alpha,p | q,p> = <"
452 << alpha <<
"," << p <<
" | " << q <<
"," << p <<
">" << std::endl;
454 const double *qp_buf;
455 const double *pq_buf;
457 tim_mo_ints_retrieve.enter_default();
459 qp_buf = accumk->retrieve_pair_block(qq,pp,intsetidx_ket);
462 pq_buf = accumk->retrieve_pair_block(pp,qq,intsetidx_ket);
464 tim_mo_ints_retrieve.exit_default();
468 ExEnv::outn() << indent <<
"task " << me <<
": obtained qp blocks" << std::endl;
471 memset(T_alphap, 0, blksize_int*
sizeof(
double));
472 memset(T_qp, 0, blksize_int*
sizeof(
double));
475 ExEnv::out0() << indent <<
"alpha = " << alpha <<
" p = " << p <<
" q = " << q
476 << incindent << std::endl;
479 for(iterint.start(); iterint; iterint.next()) {
480 unsigned int r = iterint.i();
481 unsigned int s = iterint.j();
482 unsigned int rs = iterint.ij();
486 const unsigned int rr = map2_intb[r];
487 const unsigned int ss = map3_intb[s];
488 RS_bra = rr*bratform_block_ncols + ss;
491 const unsigned int rr = map2_intk[r];
492 const unsigned int ss = map3_intk[s];
493 RS_ket = rr*kettform_block_ncols + ss;
497 I_alphaprs = alphap_buf[RS_bra];
505 const unsigned int rr = map32_intb[r];
506 const unsigned int ss = map23_intb[s];
507 SR_bra = ss*bratform_block_ncols + rr;
510 const unsigned int rr = map32_intk[r];
511 const unsigned int ss = map23_intk[s];
512 SR_ket = ss*kettform_block_ncols + rr;
517 I_alphapsr = alphap_buf[SR_bra];
524 ExEnv::out0() << indent <<
" r = " << r <<
" s = " << s << std::endl;
530 I_qprs = qp_buf[RS_ket];
537 ExEnv::out0() << indent <<
" <alphap|rs> = " << I_alphaprs << std::endl
538 << indent <<
" <qp|rs> = " << I_qprs << std::endl;
543 I_qpsr = qp_buf[SR_ket];
550 ExEnv::out0() <<
" <alphap|rs> = " << I_alphaprs << std::endl
551 <<
" <alphap|sr> = " << I_alphapsr << std::endl
552 <<
" <qp|rs> = " << I_qprs << std::endl
553 <<
" <qp|sr> = " << I_qpsr << std::endl;
558 T_alphaprs = DataProcess_Bra::I2T(I_alphaprs-I_alphapsr,alpha,p,r,s,
559 evals1_bra,evals2_intb,evals1_intb,evals3_intb);
562 T_alphaprs = I_alphaprs;
567 T_qprs = DataProcess_Ket::I2T(I_qprs-I_qpsr,q,p,r,s,
568 evals1_ket,evals2_intk,evals1_intk,evals3_intk);
574 T_alphap[rs] = T_alphaprs;
581 I_pqrs = pq_buf[RS_ket];
589 I_pqsr = pq_buf[SR_ket];
596 ExEnv::out0() <<
" <alphap|rs> = " << I_alphaprs << std::endl
597 <<
" <alphap|rs> = " << I_alphapsr << std::endl
598 <<
" <pq|rs> = " << I_pqrs << std::endl
599 <<
" <pq|sr> = " << I_pqsr << std::endl;
604 T_alphaprs = DataProcess_Bra::I2T(I_alphaprs-I_alphapsr,alpha,p,r,s,
605 evals1_bra,evals2_intb,evals1_intb,evals3_intb);
608 T_alphaprs = I_alphaprs;
613 T_qprs = DataProcess_Ket::I2T(I_pqsr-I_pqrs,q,p,r,s,
614 evals1_ket,evals2_intk,evals1_intk,evals3_intk);
620 T_alphap[rs] = T_alphaprs;
627 double T_alphapqp = tpcontract->contract(T_alphap,T_qp);
631 <<
" <alphap|qp> = " << T_alphapqp << std::endl;
634 T.accumulate_element(alpha,q,T_alphapqp);
638 accumk->release_pair_block(qq,pp,intsetidx_ket);
641 accumk->release_pair_block(pp,qq,intsetidx_ket);
649 if(fetch_alphap_block && (!r12coeffs_bra)) {
650 accumb->release_pair_block(alphaalpha,pp,intsetidx_bra);
658 if (accumb != accumk) {
659 if (accumk->data_persistent()) accumk->deactivate();
663 if (accumb->data_persistent()) accumb->deactivate();
671 ExEnv::out0() << indent <<
"Exited generic contraction (" << label <<
")" << std::endl;