30 #ifndef _mpqc_src_lib_chemistry_qc_mbptr12_srr12intermediatesutil_h
31 #define _mpqc_src_lib_chemistry_qc_mbptr12_srr12intermediatesutil_h
35 #include <TiledArray/bitset.h>
40 std::shared_ptr<typename SingleReference_R12Intermediates<T>::TArray22>
41 SingleReference_R12Intermediates<T>::ab_O_cd(
const std::string& key,
44 typedef typename TArray22::value_type value_type;
46 Ref<TwoBodyMOIntsTransform> tform = r12world_->world()->moints_runtime4()->get(key);
48 Ref<DistArray4> darray4 = tform->ints_distarray4();
52 std::vector<int> tasks_with_access;
53 const int ntasks_with_access = darray4->tasks_with_access(tasks_with_access);
54 MPQC_ASSERT(ntasks_with_access == world_.nproc());
55 MPQC_ASSERT(ntasks_with_access == r12world_->world()->msg()->n());
57 const size_t n1 = darray4->ni();
58 const size_t n2 = darray4->nj();
59 const size_t n3 = darray4->nx();
60 const size_t n4 = darray4->ny();
64 std::vector<size_t> i1_hashmarks(n1+1, 1);
66 std::partial_sum(i1_hashmarks.begin(), i1_hashmarks.end(), i1_hashmarks.begin());
67 std::vector<size_t> i2_hashmarks(n2+1, 1);
69 std::partial_sum(i2_hashmarks.begin(), i2_hashmarks.end(), i2_hashmarks.begin());
71 std::vector<TA::TiledRange1> hashmarks;
72 hashmarks.push_back(TiledArray::TiledRange1(i1_hashmarks.begin(), i1_hashmarks.end()));
73 hashmarks.push_back(TiledArray::TiledRange1(i2_hashmarks.begin(), i2_hashmarks.end()));
75 TiledArray::TiledRange i1i2_trange(hashmarks.begin(), hashmarks.end());
78 std::shared_ptr<TArray22> i1i2_g_p1p2(
new TArray22(world_, i1i2_trange));
81 std::vector<size_t> p1p2_start(2, 0);
82 std::vector<size_t> p1p2_finish(2); p1p2_finish[0] = n3; p1p2_finish[1] = n4;
83 TA::Range p1p2_range(p1p2_start, p1p2_finish);
87 std::vector<double> p1p2_block(n3 * n4);
89 std::vector<size_t> i1i2(2, 0);
90 for(i1i2[0] = 0; i1i2[0]<n1; ++i1i2[0]) {
91 for(i1i2[1] = 0; i1i2[1]<n2; ++i1i2[1]) {
92 if (i1i2_g_p1p2->is_local(i1i2)) {
94 darray4->retrieve_pair_block(i1i2[0], i1i2[1], te_type, &p1p2_block[0]);
96 madness::Future < value_type >
97 tile((value_type(i1i2_g_p1p2->trange().make_tile_range(i1i2),
98 (
typename value_type::value_type(p1p2_range,
105 i1i2_g_p1p2->set(i1i2, tile);
107 darray4->release_pair_block(i1i2[0], i1i2[1], te_type);
118 template <
typename T>
120 SingleReference_R12Intermediates<T>::_(
const std::string& key) {
121 auto v = tarray22_registry_.find(key);
122 if (tarray22_registry_.find(key) == tarray22_registry_.end()) {
123 ParsedTwoBodyFourCenterIntKey pkey(key);
126 std::string operset_label;
127 const unsigned int oper_idx = 0;
128 if (pkey.oper() ==
"g") {
129 operset_label =
"ERI";
131 else if (pkey.oper() ==
"gr") {
132 operset_label =
"R12_m1_G12[0]";
134 else if (pkey.oper() ==
"r") {
135 operset_label =
"R12_0_G12[0]";
137 else if (pkey.oper() ==
"r2") {
138 operset_label =
"R12_0_G12[0,0]";
140 else if (pkey.oper() ==
"rTr") {
141 operset_label =
"G12_T1_G12[0,0]";
144 throw ProgrammingError(
"SingleReference_R12Intermediates<T>::_ : invalid operator key",__FILE__,__LINE__);
147 auto bra1 = to_space(pkey.bra1());
148 auto bra2 = to_space(pkey.bra2());
149 auto ket1 = to_space(pkey.ket1());
150 auto ket2 = to_space(pkey.ket2());
152 std::string tform_key = ParsedTwoBodyFourCenterIntKey::key(bra1, bra2, ket1, ket2,
155 tarray22_registry_[key] = ab_O_cd(tform_key, oper_idx);
156 v = tarray22_registry_.find(key);
162 template <
typename T>
166 auto v = tarray4_registry_.find(key);
167 if (tarray4_registry_.find(key) == tarray4_registry_.end()) {
172 std::string operset_label;
176 const unsigned int oper_idx = 0;
177 if (pkey.oper() ==
"g") {
178 operset_label =
"ERI";
180 else if (pkey.oper() ==
"gr") {
181 operset_label =
"R12_m1_G12[0]";
183 else if (pkey.oper() ==
"r") {
184 operset_label =
"R12_0_G12[0]";
186 else if (pkey.oper() ==
"r2") {
187 operset_label =
"R12_0_G12[0,0]";
189 else if (pkey.oper() ==
"rTr") {
190 operset_label =
"G12_T1_G12[0,0]";
192 else if (pkey.oper() ==
"gamma") {
195 else if (pkey.oper() ==
"T2") {
198 else if (pkey.oper() ==
"L2") {
202 throw ProgrammingError(
"SingleReference_R12Intermediates<T>::ijxy : invalid operator key",__FILE__,__LINE__);
205 auto bra1 = to_space(pkey.bra1());
206 auto bra2 = to_space(pkey.bra2());
207 auto ket1 = to_space(pkey.ket1());
208 auto ket2 = to_space(pkey.ket2());
209 auto oreg = r12world_->world()->tfactory()->orbital_registry();
214 throw ProgrammingError(
"SingleReference_R12Intermediates<T>::ijxy: asked for rdm2, but it had not been given");
216 auto bra1_space = oreg->value(bra1);
217 auto bra2_space = oreg->value(bra2);
218 auto ket1_space = oreg->value(ket1);
219 auto ket2_space = oreg->value(ket2);
220 const auto& rdm_space = rdm2_->orbs();
222 darray4 = rdm2_->da4();
223 if (not (*bra1_space == *rdm_space &&
224 *bra2_space == *rdm_space &&
225 *ket1_space == *rdm_space &&
226 *ket2_space == *rdm_space )) {
227 DistArray4Dimensions dims(1, bra1_space->rank(), bra2_space->rank(), ket1_space->rank(), ket2_space->rank());
229 std::vector<int> bra1_map =
sc::map(*rdm_space, *bra1_space,
true);
230 std::vector<int> bra2_map =
sc::map(*rdm_space, *bra2_space,
true);
231 std::vector<int> ket1_map =
sc::map(*rdm_space, *ket1_space,
true);
232 std::vector<int> ket2_map =
sc::map(*rdm_space, *ket2_space,
true);
234 std::vector<double> buf(rdm_space->rank() * rdm_space->rank());
235 std::vector<double> map_buf(ket1_space->rank() * ket2_space->rank());
238 darray4_mapped->activate();
240 for(
int b1=0; b1<bra1_space->rank(); ++b1) {
241 const int bb1 = bra1_map[b1];
242 for(
int b2=0; b2<bra2_space->rank(); ++b2) {
243 const int bb2 = bra2_map[b2];
247 const int nk1 = ket1_space->rank();
248 const int nk2 = ket2_space->rank();
249 for(
int k1=0, k12=0; k1<nk1; ++k1) {
250 const int kk1 = ket1_map[k1];
251 const int kk1_offset = kk1 * rdm_space->rank();
252 for(
int k2=0; k2<nk2; ++k2, ++k12) {
253 const int kk2 = ket2_map[k2];
254 map_buf[k12] = buf[kk1_offset + kk2];
258 darray4_mapped->store_pair_block(b1, b2, 0, &map_buf[0]);
263 if (darray4_mapped->data_persistent()) darray4_mapped->deactivate();
265 darray4 = darray4_mapped;
269 if (t2_[AlphaBeta].
null())
270 throw ProgrammingError(
"SingleReference_R12Intermediates<T>::ijxy: asked for T2, but it had not been given");
277 darray4 = t2_[AlphaBeta];
280 if (l2_[AlphaBeta].
null())
281 throw ProgrammingError(
"SingleReference_R12Intermediates<T>::ijxy: asked for L2, but it had not been given");
283 darray4 = l2_[AlphaBeta];
286 std::string tform_key = ParsedTwoBodyFourCenterIntKey::key(bra1, bra2, ket1, ket2,
296 const size_t n1 = darray4->
ni();
297 const size_t n2 = darray4->
nj();
298 const size_t n3 = darray4->
nx();
299 const size_t n4 = darray4->
ny();
302 std::vector<int> tasks_with_access;
304 MPQC_ASSERT(ntasks_with_access == world_.nproc());
305 MPQC_ASSERT(ntasks_with_access == r12world_->world()->msg()->n());
308 std::vector<size_t> i_hashmarks = space_hashmarks(bra1);
309 std::vector<size_t> j_hashmarks = space_hashmarks(bra2);
310 std::vector<size_t> x_hashmarks = space_hashmarks(ket1);
311 std::vector<size_t> y_hashmarks = space_hashmarks(ket2);
313 std::vector<TA::TiledRange1> hashmarks;
314 hashmarks.push_back(TiledArray::TiledRange1(i_hashmarks.begin(), i_hashmarks.end()));
315 hashmarks.push_back(TiledArray::TiledRange1(j_hashmarks.begin(), j_hashmarks.end()));
316 hashmarks.push_back(TiledArray::TiledRange1(x_hashmarks.begin(), x_hashmarks.end()));
317 hashmarks.push_back(TiledArray::TiledRange1(y_hashmarks.begin(), y_hashmarks.end()));
318 TiledArray::TiledRange ijxy_trange(hashmarks.begin(), hashmarks.end());
320 std::shared_ptr<TArray4d> result(
new TArray4d(world_, ijxy_trange) );
322 for(
auto t=ijxy_trange.tiles_range().begin();
323 t!=ijxy_trange.tiles_range().end();
325 if (result->is_local(*t))
327 std::array<std::size_t, 4> index; std::copy(t->begin(), t->end(), index.begin());
328 madness::Future < typename TArray4d::value_type >
329 tile((
DA4_Tile<T>(result.get(), index, darray4, oper_idx)
333 result->set(*t, tile);
336 tarray4_registry_[key] = result;
337 v = tarray4_registry_.find(key);
343 template <
typename T>
347 auto v = tarray22d_registry_.find(key);
348 if (tarray22d_registry_.find(key) == tarray22d_registry_.end()) {
353 std::string operset_label;
354 const unsigned int oper_idx = 0;
355 if (pkey.oper() ==
"g") {
356 operset_label =
"ERI";
358 else if (pkey.oper() ==
"gr") {
359 operset_label =
"R12_m1_G12[0]";
361 else if (pkey.oper() ==
"r") {
362 operset_label =
"R12_0_G12[0]";
364 else if (pkey.oper() ==
"r2") {
365 operset_label =
"R12_0_G12[0,0]";
367 else if (pkey.oper() ==
"rTr") {
368 operset_label =
"G12_T1_G12[0,0]";
371 throw ProgrammingError(
"SingleReference_R12Intermediates<T>::ij_xy : invalid operator key",__FILE__,__LINE__);
374 auto bra1 = to_space(pkey.bra1());
375 auto bra2 = to_space(pkey.bra2());
376 auto ket1 = to_space(pkey.ket1());
377 auto ket2 = to_space(pkey.ket2());
379 std::string tform_key = ParsedTwoBodyFourCenterIntKey::key(bra1, bra2, ket1, ket2,
387 const size_t n1 = darray4->
ni();
388 const size_t n2 = darray4->
nj();
389 const size_t n3 = darray4->
nx();
390 const size_t n4 = darray4->
ny();
393 std::vector<int> tasks_with_access;
395 MPQC_ASSERT(ntasks_with_access == world_.nproc());
396 MPQC_ASSERT(ntasks_with_access == r12world_->world()->msg()->n());
400 std::vector<size_t> i_hashmarks(n1+1, 1);
402 std::partial_sum(i_hashmarks.begin(), i_hashmarks.end(), i_hashmarks.begin());
403 std::vector<size_t> j_hashmarks(n2+1, 1);
405 std::partial_sum(j_hashmarks.begin(), j_hashmarks.end(), j_hashmarks.begin());
407 std::vector<TA::TiledRange1> hashmarks;
408 hashmarks.push_back(TiledArray::TiledRange1(i_hashmarks.begin(), i_hashmarks.end()));
409 hashmarks.push_back(TiledArray::TiledRange1(j_hashmarks.begin(), j_hashmarks.end()));
410 TiledArray::TiledRange ij_trange(hashmarks.begin(), hashmarks.end());
412 std::shared_ptr<TArray22d> result(
new TArray22d(world_, ij_trange) );
414 for(
auto t=ij_trange.tiles_range().begin();
415 t!=ij_trange.tiles_range().end();
417 if (result->is_local(*t))
419 std::array<std::size_t, 2> index; std::copy(t->begin(), t->end(), index.begin());
420 madness::Future < typename TArray22d::value_type >
425 result->set(*t, tile);
428 tarray22d_registry_[key] = result;
429 v = tarray22d_registry_.find(key);
435 template <
typename T>
439 auto v = tarray2_registry_.find(key);
440 if (v == tarray2_registry_.end()) {
445 auto bra_id = to_space(pkey.bra());
446 auto ket_id = to_space(pkey.ket());
448 auto oreg = r12world_->world()->tfactory()->orbital_registry();
449 auto freg = r12world_->world()->fockbuild_runtime();
450 auto bra = oreg->value(bra_id);
451 auto ket = oreg->value(ket_id);
452 auto nbra = bra->rank();
453 auto nket = ket->rank();
457 if (pkey.oper() ==
"J")
458 operator_matrix = freg->get(ParsedOneBodyIntKey::key(bra_id, ket_id,
"J"));
459 else if (pkey.oper() ==
"K")
460 operator_matrix = freg->get(ParsedOneBodyIntKey::key(bra_id, ket_id,
"K"));
461 else if (pkey.oper() ==
"F")
462 operator_matrix = freg->get(ParsedOneBodyIntKey::key(bra_id, ket_id,
"F"));
463 else if (pkey.oper() ==
"h")
464 operator_matrix = freg->get(ParsedOneBodyIntKey::key(bra_id, ket_id,
"H"));
465 else if (pkey.oper() ==
"hJ")
466 operator_matrix = freg->get(ParsedOneBodyIntKey::key(bra_id, ket_id,
"H"))
467 + freg->get(ParsedOneBodyIntKey::key(bra_id, ket_id,
"J"));
468 else if (pkey.oper().find(
"mu_") == 0 || pkey.oper().find(
"q_") == 0 ||
469 pkey.oper().find(
"dphi_") == 0 || pkey.oper().find(
"ddphi_") == 0) {
470 operator_matrix = freg->get(ParsedOneBodyIntKey::key(bra_id, ket_id, pkey.oper()));
472 else if (pkey.oper() ==
"gamma")
473 operator_matrix = this->rdm1(bra, ket);
474 else if (pkey.oper() ==
"I") {
475 operator_matrix = bra->coefs()->kit()->matrix(bra->coefs().coldim(), ket->coefs().coldim());
477 operator_matrix.assign(0.0);
478 for(
int i=0; i<nbra; ++i)
479 operator_matrix.set_element(i,i,1.0);
482 operator_matrix =
sc::overlap(*bra,*ket,operator_matrix->kit());
485 else if (pkey.oper() ==
"T1") {
488 if (t1_.ncol() != oreg->value(ket_id)->rank())
489 throw ProgrammingError(
"SingleReference_R12Intermediates::xy() -- T1.ncol() != nvir_act",
491 operator_matrix = t1_;
494 if (t1_cabs_.ncol() == oreg->value(
"a'")->rank())
495 throw ProgrammingError(
"SingleReference_R12Intermediates::xy() -- asked for <i|T1|a> but T1_cabs does not include conv. virtuals",
499 MPQC_ASSERT(t1_cabs_.ncol() == allvir->
rank());
500 RefSCMatrix t1_subblock = t1_cabs_.kit()->matrix(t1_cabs_.rowdim(),
501 vir_act->
coefs()->coldim());
502 std::vector<int> vir_to_allvir =
sc::map(*allvir, *vir_act,
false);
503 const int nocc_act = t1_subblock.nrow();
504 const int nvir_act = vir_act->
rank();
505 for(
int i=0; i<nocc_act; ++i) {
506 for(
int a=0; a<nvir_act; ++a) {
507 const int Ap = vir_to_allvir[a];
508 t1_subblock.set_element(i, a, t1_cabs_.get_element(i, Ap));
511 operator_matrix = t1_subblock;
515 MPQC_ASSERT(ket_id ==
"a'" || ket_id ==
"A'");
516 MPQC_ASSERT(t1_cabs_);
517 MPQC_ASSERT(oreg->value(ket_id)->rank() == t1_cabs_.ncol());
518 operator_matrix = t1_cabs_;
521 else if (pkey.oper() ==
"L1") {
523 MPQC_ASSERT(oreg->value(bra_id)->rank() == l1_.nrow());
524 MPQC_ASSERT(oreg->value(ket_id)->rank() == l1_.ncol());
525 operator_matrix = l1_;
528 std::ostringstream oss;
529 oss <<
"SingleReference_R12Intermediates<T>::xy -- operator " << pkey.oper() <<
" is not recognized";
535 std::vector<size_t> bra_hashmarks = space_hashmarks(bra_id);
536 std::vector<size_t> ket_hashmarks = space_hashmarks(ket_id);
538 std::vector<TA::TiledRange1> hashmarks;
539 hashmarks.push_back(TiledArray::TiledRange1(bra_hashmarks.begin(), bra_hashmarks.end()));
540 hashmarks.push_back(TiledArray::TiledRange1(ket_hashmarks.begin(), ket_hashmarks.end()));
541 TiledArray::TiledRange braket_trange(hashmarks.begin(), hashmarks.end());
543 std::shared_ptr<TArray2> result(
new TArray2(world_, braket_trange) );
545 for(
auto t=result->pmap()->begin();
546 t!=result->pmap()->end();
550 auto tile_range = result->trange().make_tile_range(*t);
551 std::vector<double> ptr_data(tile_range.volume());
553 for(
size_t r=tile_range.lobound()[0], rc=0;
554 r != tile_range.upbound()[0];
556 for(
size_t c=tile_range.lobound()[1];
557 c != tile_range.upbound()[1];
559 ptr_data[rc] = operator_matrix->get_element(r,c);
563 madness::Future < typename TArray2::value_type >
564 tile(
typename TArray2::value_type(tile_range, &ptr_data[0]));
567 result->set(*t, tile);
570 tarray2_registry_[key] = result;
571 v = tarray2_registry_.find(key);
577 template <
typename T>
578 TA::expressions::TsrExpr<const typename SingleReference_R12Intermediates<T>::TArray4d,
true>
580 const TArray4d& tarray4 = ijxy(key);
583 std::array<std::string, 4> ind = {{pkey.bra1(), pkey.bra2(), pkey.ket1(), pkey.ket2()}};
584 for(
auto v=ind.begin(); v!=ind.end(); ++v) {
585 if (ParsedTransformedOrbitalSpaceKey::valid_key(*v) ) {
591 const std::string annotation = ind[0] +
"," + ind[1] +
"," + ind[2] +
"," + ind[3];
592 return tarray4(annotation);
595 template <
typename T>
596 TA::expressions::TsrExpr<const typename SingleReference_R12Intermediates<T>::TArray2,
true>
598 const TArray2& tarray2 = xy(key);
601 std::array<std::string, 2> ind = {{pkey.bra(), pkey.ket()}};
602 for(
auto v=ind.begin(); v!=ind.end(); ++v) {
603 if (ParsedTransformedOrbitalSpaceKey::valid_key(*v) ) {
609 const std::string annotation = ind[0] +
"," + ind[1];
610 return tarray2(annotation);
613 template <
typename T>
615 template <
typename T>
618 template <
typename T>
619 TA::expressions::TsrExpr<const typename SingleReference_R12Intermediates<T>::TArray4Tg,
true>
624 auto v = tarray4tg_registry_.find(key);
625 if (v == tarray4tg_registry_.end()) {
627 if (pkey.oper() !=
"Tg") {
628 std::ostringstream oss;
629 oss <<
"SingleReference_R12Intermediates<T>::_Tg : " << pkey.oper() <<
" is an invalid operator key";
634 auto bra1 = to_space(pkey.bra1());
635 auto bra2 = to_space(pkey.bra2());
636 auto ket1 = to_space(pkey.ket1());
637 auto ket2 = to_space(pkey.ket2());
639 if (not (bra1 == bra2 && bra1 == ket1 && bra1 == ket2)) {
640 throw ProgrammingError(
"SingleReference_R12Intermediates<T>::_Tg : all spaces must be the same", __FILE__, __LINE__);
644 std::vector<size_t> i_hashmarks = space_hashmarks(bra1);
645 std::vector<size_t> j_hashmarks = space_hashmarks(bra2);
646 std::vector<size_t> x_hashmarks = space_hashmarks(ket1);
647 std::vector<size_t> y_hashmarks = space_hashmarks(ket2);
649 std::vector<TA::TiledRange1> hashmarks;
650 hashmarks.push_back(TiledArray::TiledRange1(i_hashmarks.begin(), i_hashmarks.end()));
651 hashmarks.push_back(TiledArray::TiledRange1(j_hashmarks.begin(), j_hashmarks.end()));
652 hashmarks.push_back(TiledArray::TiledRange1(x_hashmarks.begin(), x_hashmarks.end()));
653 hashmarks.push_back(TiledArray::TiledRange1(y_hashmarks.begin(), y_hashmarks.end()));
654 TiledArray::TiledRange ijxy_trange(hashmarks.begin(), hashmarks.end());
656 std::shared_ptr<TArray4Tg> result(
new TArray4Tg(world_, ijxy_trange) );
658 for(
auto t=ijxy_trange.tiles_range().begin();
659 t!=ijxy_trange.tiles_range().end();
661 if (result->is_local(*t))
663 std::array<std::size_t, 4> index; std::copy(t->begin(), t->end(), index.begin());
664 madness::Future < typename TArray4Tg::value_type >
665 tile((
typename TArray4Tg::value_type(result.get(), index, &tg_s0_gen)
669 result->set(*t, tile);
672 tarray4tg_registry_[key] = result;
673 v = tarray4tg_registry_.find(key);
677 std::array<std::string, 4> ind = {{pkey.bra1(), pkey.bra2(), pkey.ket1(), pkey.ket2()}};
678 for(
auto v=ind.begin(); v!=ind.end(); ++v) {
679 if (ParsedTransformedOrbitalSpaceKey::valid_key(*v) ) {
685 const std::string annotation = ind[0] +
"," + ind[1] +
"," + ind[2] +
"," + ind[3];
686 return tarray4(annotation);
689 namespace expressions {
691 template <
typename ArgType,
bool Transpose = false>
692 struct trace_tensor2_op :
public std::binary_function<ArgType, ArgType, TA::Tensor<typename ArgType::numeric_type> > {
693 typedef typename ArgType::numeric_type numeric_type;
694 typedef TA::Tensor<typename ArgType::numeric_type> result_type;
695 typedef result_type value_type;
697 static bool is_dense(
bool first_dense,
bool second_dense) {
700 static bool is_zero(
const bool first_zero,
const bool second_zero) {
701 return first_zero || second_zero;
704 template <
typename Left,
typename Right>
705 static void shape(::TiledArray::detail::Bitset<>& result,
const Left& left,
const Right& right) {
706 result = ::TiledArray::detail::Bitset<>(0);
710 void scale(numeric_type s) {
715 operator()(
const ArgType& arg1,
const ArgType& arg2)
const {
716 TA_ASSERT(arg1.size() == 1);
717 TA_ASSERT(arg2.size() == 1);
718 TA_ASSERT(arg1.data()->size() == arg2.data()->size());
719 TA_ASSERT(arg1.range() == arg2.range());
721 numeric_type dot_product;
723 dot_product = TA::math::dot(arg1.data()->size(), arg1.data()->data(), arg2.data()->data());
725 const integer nrow1 = arg1.data()->range().size()[0];
726 const integer ncol1 = arg1.data()->range().size()[1];
727 TA_ASSERT(ncol1 == arg2.data()->range().size()[0]);
728 const integer unit_stride = 1;
731 const numeric_type* ptr1 = arg1.data()->data();
732 const numeric_type* ptr2 = arg2.data()->data();
733 for(integer row1=0; row1<nrow1; ++row1, ptr1+=ncol1, ++ptr2) {
734 dot_product += TA::math::dot(ncol1, ptr1, unit_stride, ptr2, nrow1);
739 result_type result(arg1.range(), &dot_product);
740 return result * scale_;
743 result_type operator()(
const TiledArray::ZeroTensor&,
const ArgType&) {
745 return result_type();
748 result_type operator()(
const ArgType&,
const TiledArray::ZeroTensor&) {
750 return result_type();
758 template <
typename ArgType,
bool Transpose = false>
759 struct diag_tensor2_op :
public std::unary_function<ArgType, TA::Tensor<typename ArgType::numeric_type> > {
760 typedef typename ArgType::numeric_type numeric_type;
761 typedef TA::Tensor<typename ArgType::numeric_type> result_type;
762 typedef result_type value_type;
764 static bool is_dense(
bool arg_dense) {
767 static bool is_zero(
const bool arg_zero) {
771 template <
typename Arg>
772 static void shape(::TiledArray::detail::Bitset<>& result,
const Arg& arg) {
773 result = ::TiledArray::detail::Bitset<>(0);
777 void scale(numeric_type s) {
782 operator()(
const ArgType& arg)
const {
783 TA_ASSERT(arg.size() == 1);
785 numeric_type result_value = 0;
786 const auto& ij = arg.range().start();
787 const auto& pq_size = arg.data()->range().size();
789 result_value = arg.data()->data()[ij[0] * pq_size[1] + ij[1]];
792 result_value = arg.data()->data()[ij[1] * pq_size[1] + ij[0]];
795 result_type result(arg.range(), &result_value);
796 return result * scale_;
799 result_type operator()(
const TiledArray::ZeroTensor&) {
801 return result_type();
810 template <
typename T>
812 SingleReference_R12Intermediates<T>::to_space(
const std::string& index) {
814 bool tformed_space = ParsedTransformedOrbitalSpaceKey::valid_key(index);
816 ParsedTransformedOrbitalSpaceKey pkey(index);
819 const std::string space_label = to_space(pkey.label());
820 std::string space_key = ParsedTransformedOrbitalSpaceKey::key(space_label, pkey.spin(),
821 pkey.support_label(), pkey.support_spin(),
822 pkey.transform_operator());
823 auto oreg = r12world_->world()->tfactory()->orbital_registry();
824 auto freg = r12world_->world()->fockbuild_runtime();
826 if (not oreg->key_exists(space_key)) {
827 std::string support_key = ParsedOrbitalSpaceKey::key(to_space(pkey.support_label()), pkey.support_spin());
828 std::string target_key = ParsedOrbitalSpaceKey::key(space_label, pkey.spin());
830 Ref<OrbitalSpace> target_space = oreg->value(target_key);
831 Ref<OrbitalSpace> support_space = oreg->value(support_key);
832 RefSCMatrix support_coefs = support_space->coefs();
834 RefSCMatrix operator_matrix;
835 switch(pkey.transform_operator()) {
837 operator_matrix = freg->get(ParsedOneBodyIntKey::key(support_key, target_key,
"J"));
840 operator_matrix = freg->get(ParsedOneBodyIntKey::key(support_key, target_key,
"K"));
843 operator_matrix = freg->get(ParsedOneBodyIntKey::key(support_key, target_key,
"F"));
846 operator_matrix = freg->get(ParsedOneBodyIntKey::key(support_key, target_key,
"H"))
847 + freg->get(ParsedOneBodyIntKey::key(support_key, target_key,
"J"));
850 operator_matrix = this->rdm1(support_space, target_space);
853 throw ProgrammingError(
"SingleReference_R12Intermediates<T>::to_space -- transformed spaces only with Fock-like operators are supported now",
857 Ref<OrbitalSpace> tformed_space =
new OrbitalSpace(space_key, space_key,
858 target_space, support_coefs * operator_matrix,
859 support_space->basis());
866 return to_space_(index);
869 template <
typename T>
871 const Ref<OrbitalSpace>& col_space)
const {
873 RefSymmSCMatrix gamma_total = r12world_->refwfn()->ordm_occ_sb(Alpha) + r12world_->refwfn()->ordm_occ_sb(Beta);
874 Ref<OrbitalSpace> occ = r12world_->refwfn()->occ_sb(Alpha);
876 std::vector<int> col_to_occ;
877 std::vector<int> row_to_occ;
879 const bool require_same_basis =
true;
880 col_to_occ =
map(*occ, *col_space, require_same_basis);
881 row_to_occ =
map(*occ, *row_space, require_same_basis);
884 throw ProgrammingError(
"requested RDM1 in spaces x and y, but x and y are not supported by the same basis",
887 RefSCMatrix result = gamma_total.kit()->matrix(row_space->dim(), col_space->dim());
889 const int nr = result.nrow();
890 const int nc = result.ncol();
891 for(
int r=0; r<nr; ++r) {
892 const int rr = row_to_occ[r];
894 for(
int c=0; c<nc; ++c) {
895 const int cc = col_to_occ[c];
897 result.set_element(r, c, gamma_total.get_element(rr, cc));
905 std::string SingleReference_R12Intermediates<T>::to_space_(std::string index) {
907 index.erase(std::remove_if(index.begin(), index.end(),
909 return c >=
'0' && c<=
'9';
913 if (index ==
"i" || index ==
"j" || index ==
"k" || index ==
"l")
915 if (index ==
"m" || index ==
"n")
917 if (index ==
"i'" || index ==
"j'" || index ==
"k'" || index ==
"l'")
919 if (index ==
"a" || index ==
"b" || index ==
"c" || index ==
"d")
921 if (index ==
"e" || index ==
"f")
923 if (index ==
"a" || index ==
"b" || index ==
"c" || index ==
"d")
925 if (index ==
"p" || index ==
"q" || index ==
"r" || index ==
"s")
927 if (index ==
"p'" || index ==
"q'" || index ==
"r'" || index ==
"s'")
929 if (index ==
"a'" || index ==
"b'" || index ==
"c'" || index ==
"d'")
931 if (index ==
"A'" || index ==
"B'" || index ==
"C'" || index ==
"D'")
934 std::ostringstream oss;
935 oss <<
"SingleReference_R12Intermediates::to_space(): index label " << index <<
" not in the current dictionary:";
936 throw ProgrammingError(oss.str().c_str(),
940 template <
typename T>
942 SingleReference_R12Intermediates<T>::space_hashmarks(std::string space_label)
const {
944 const bool tformed_space = ParsedTransformedOrbitalSpaceKey::valid_key(space_label);
946 ParsedTransformedOrbitalSpaceKey ptkey(space_label);
947 space_label = ptkey.label();
950 auto oreg = r12world_->world()->tfactory()->orbital_registry();
951 size_t rank = oreg->value(space_label)->rank();
952 std::vector<size_t> hashmarks(2,0); hashmarks[1] = rank;
953 if (space_label ==
"i" || space_label ==
"m") {
955 const int nproc = r12world_->world()->msg()->n();
956 const size_t desired_tilesize = std::max(4 ,
957 std::min( (
int)floor((
double)rank / sqrt((
double)nproc)), 10)
959 const size_t ntiles = (rank+desired_tilesize-1)/desired_tilesize;
960 const size_t tilesize = (rank + ntiles - 1)/ ntiles;
961 hashmarks.resize(ntiles+1);
963 for(
size_t i=1; i<ntiles; ++i)
964 hashmarks[i] = hashmarks[i-1] + tilesize;
965 hashmarks.back() = rank;
973 std::vector<std::string>
974 split(
const std::string& key,
977 std::stringstream ss(key);
979 std::vector<std::string> tokens;
980 while (std::getline(ss, item, separator)) {
981 tokens.push_back(item);
989 template <
typename T>
template <
size_t NDIM>
991 SingleReference_R12Intermediates<T>::make_trange(
const std::array<std::string, NDIM>& spaces)
const {
993 std::vector<TA::TiledRange1> hashmarks;
994 for(
auto id=spaces.begin();
id!=spaces.end(); ++id) {
995 std::vector<size_t> hashmark = space_hashmarks(*
id);
996 hashmarks.push_back(TiledArray::TiledRange1(hashmark.begin(), hashmark.end()));
998 return TA::TiledRange(hashmarks.begin(), hashmarks.end());
1003 template <
typename T,
typename Index>
1005 sieve_tensor(TA::Array<T, 2>* result,
1007 madness::Future<
typename TA::Array<T, 2>::value_type > source_tile,
1008 TA::Array<T, 2>* source,
1010 std::vector<int>* row_map,
1011 std::vector<int>* col_map) {
1013 typedef TA::Array<T, 2> TArray2;
1015 auto result_trange = result->trange().make_tile_range(t);
1016 auto source_trange = source->trange().make_tile_range(t_source);
1018 std::vector<T> ptr_result(result_trange.volume(), T(0.0));
1020 for(
size_t r=source_trange.start()[0], rc=0;
1021 r != source_trange.finish()[0];
1023 const int rr = row_map->operator[](r);
1025 for(
size_t c=source_trange.start()[1];
1026 c != source_trange.finish()[1];
1029 const int cc = col_map->operator[](c);
1040 madness::Future < typename TArray2::value_type >
1041 tile(
typename TArray2::value_type(result_trange, &ptr_result[0]));
1044 result->set(*t, tile);
1049 template <
typename T>
1052 const std::string& output_annotation) {
1055 std::string input_key;
1056 for(
auto i = tarray2_registry_.begin();
1057 i!=tarray2_registry_.end(); ++i) {
1058 if (i->second.get() == &input) {
1059 input_key = i->first;
1063 MPQC_ASSERT(input_key.empty() ==
false);
1065 std::vector<std::string> output_space_keys = split(output_annotation,
',');
1066 MPQC_ASSERT(output_space_keys.size() == 2);
1068 ParsedOneBodyIntKey input_pkey(input_key);
1069 ParsedOneBodyIntKey output_pkey(ParsedOneBodyIntKey::key(output_space_keys[0],
1070 output_space_keys[1],
1071 input_pkey.oper()));
1073 auto v = tarray2_registry_.find(output_pkey.key());
1074 if (v == tarray2_registry_.end()) {
1077 auto ibra_id = to_space(input_pkey.bra());
1078 auto iket_id = to_space(input_pkey.ket());
1079 auto obra_id = to_space(output_pkey.bra());
1080 auto oket_id = to_space(output_pkey.ket());
1082 auto oreg = r12world_->world()->tfactory()->orbital_registry();
1083 auto freg = r12world_->world()->fockbuild_runtime();
1084 auto ibra = oreg->value(ibra_id);
1085 auto iket = oreg->value(iket_id);
1086 auto obra = oreg->value(obra_id);
1087 auto oket = oreg->value(oket_id);
1089 auto nbra = obra->rank();
1090 auto nket = oket->rank();
1092 std::vector<int> bra_map =
map(*obra, *ibra);
1093 std::vector<int> ket_map =
map(*oket, *iket);
1096 std::array<std::string, 2> ospaces = {{obra_id, oket_id}};
1097 TA::TiledRange output_trange = make_trange(ospaces);
1098 std::shared_ptr<TArray2> result(
new TArray2(world_, output_trange) );
1101 for(
auto t=result->pmap()->begin();
1102 t!=result->pmap()->end();
1110 world_.taskq.add(& detail::sieve_tensor,
1111 &result, *t, input.find(t_input), &bra_map, &ket_map);
1114 tarray2_registry_[output_pkey.key()] = result;
1115 v = tarray2_registry_.find(output_pkey.key());
1119 return *(v->second);
1123 template <
typename T>
1124 std::ostream&
operator<<(std::ostream& os,
const DA4_Tile<T>& t) {
1125 os << typename DA4_Tile<T>::eval_type(t);
1129 template <
typename T>
1130 std::ostream&
operator<<(std::ostream& os,
const DA4_Tile34<T>& t) {
1131 os << typename DA4_Tile34<T>::eval_type(t);
1138 #endif // end of header guard