00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef __GNUG__
00029 #pragma interface
00030 #endif
00031
00032 #ifndef _chemistry_qc_mbptr12_contracttbinttensor_h
00033 #define _chemistry_qc_mbptr12_contracttbinttensor_h
00034
00035 #include <cmath>
00036 #include <util/misc/regtime.h>
00037 #include <chemistry/qc/mbptr12/pairiter.h>
00038 #include <chemistry/qc/mbptr12/utils.h>
00039 #include <chemistry/qc/mbptr12/utils.impl.h>
00040 #include <chemistry/qc/mbptr12/r12int_eval.h>
00041 #include <chemistry/qc/mbptr12/print.h>
00042
00043 namespace sc {
00044
00045 template <bool CorrFactorInBra,
00046 bool CorrFactorInKet,
00047 bool CorrFactorInInt>
00048 void
00049 R12IntEval::contract_tbint_tensor(
00050 RefSCMatrix& T,
00051 TwoBodyInt::tbint_type tbint_type_bra,
00052 TwoBodyInt::tbint_type tbint_type_ket,
00053 const Ref<OrbitalSpace>& space1_bra,
00054 const Ref<OrbitalSpace>& space2_bra,
00055 const Ref<OrbitalSpace>& space1_intb,
00056 const Ref<OrbitalSpace>& space2_intb,
00057 const Ref<OrbitalSpace>& space1_ket,
00058 const Ref<OrbitalSpace>& space2_ket,
00059 const Ref<OrbitalSpace>& space1_intk,
00060 const Ref<OrbitalSpace>& space2_intk,
00061 bool antisymmetrize,
00062 const std::vector< Ref<TwoBodyMOIntsTransform> >& tforms_bra
00063 const std::vector< Ref<TwoBodyIntDescr> >& intdescrs_bra
00064 )
00065 {
00066
00067 const bool part1_strong_equiv_part2 = (space1_bra==space2_bra &&
00068 space1_ket==space2_ket);
00069
00070 const bool part1_weak_equiv_part2 = (space1_bra->rank()==space2_bra->rank() &&
00071 space1_ket->rank()==space2_ket->rank());
00072
00073 const bool part1_intequiv_part2 = (space1_intb==space2_intb &&
00074 space1_intk==space2_intk);
00075
00076 bool correct_semantics = (antisymmetrize && (part1_weak_equiv_part2 ||
00077 part1_strong_equiv_part2) ) ||
00078 !antisymmetrize;
00079
00080 correct_semantics = ( correct_semantics &&
00081 (space1_intb->rank() == space1_intk->rank()) &&
00082 (space2_intb->rank() == space2_intk->rank()) );
00083 if (!correct_semantics)
00084 throw ProgrammingError("R12IntEval::contract_tbint_tensor_direct_() -- incorrect call semantics",
00085 __FILE__,__LINE__);
00086
00087
00088
00089
00090
00091 const bool alphabeta = !(antisymmetrize &&
00092 part1_strong_equiv_part2 &&
00093 part1_intequiv_part2);
00094
00095 const bool CorrFactorInBraInt = CorrFactorInBra && CorrFactorInInt;
00096 const bool CorrFactorInKetInt = CorrFactorInKet && CorrFactorInInt;
00097
00098 const unsigned int nbrasets = (CorrFactorInBra ? corrfactor()->nfunctions() : 1);
00099 const unsigned int nketsets = (CorrFactorInKet ? corrfactor()->nfunctions() : 1);
00100 const unsigned int nintsets = (CorrFactorInInt ? corrfactor()->nfunctions() : 1);
00101 const unsigned int nbraintsets = (CorrFactorInBraInt ? -1 : nbrasets*nintsets);
00102 const unsigned int nketintsets = (CorrFactorInKetInt ? -1 : nketsets*nintsets);
00103
00104
00105
00106
00107 typedef std::vector< Ref<TwoBodyMOIntsTransform> > tformvec;
00108 tformvec transforms_bra = tforms_bra;
00109 if (transforms_bra.empty()) {
00110 if (CorrFactorInBraInt) {
00111 unsigned int fbraint = 0;
00112 for(unsigned int fbra=0; fbra<nbrasets; ++fbra) {
00113 for(unsigned int fint=0; fint<nintsets; ++fint, ++fbraint) {
00114 std::string tlabel(transform_label(space1_bra,space1_intb,space2_bra,space2_intb,fbra,fint));
00115 try {
00116 transforms_bra.push_back(get_tform_(tlabel));
00117 }
00118 catch (TransformNotFound& a){
00119 Ref<MOIntsTransformFactory> tfactory = r12info()->tfactory();
00120 tfactory->set_spaces(space1_bra,space1_intb,space2_bra,space2_intb);
00121 Ref<TwoBodyMOIntsTransform> tform = tfactory->twobody_transform(
00122 MOIntsTransformFactory::StorageType_13,
00123 tlabel,
00124 intdescrs_bra[fbraint]
00125 );
00126 transforms_bra.push_back(tform);
00127 }
00128 }
00129 }
00130 }
00131 else {
00132 for(int f=0; f<nbraintsets; f++) {
00133 std::string tlabel(transform_label(space1_bra,space1_intb,space2_bra,space2_intb,f));
00134 try {
00135 transforms_bra.push_back(get_tform_(tlabel));
00136 }
00137 catch (TransformNotFound& a){
00138 Ref<MOIntsTransformFactory> tfactory = r12info()->tfactory();
00139 tfactory->set_spaces(space1_bra,space1_intb,space2_bra,space2_intb);
00140 Ref<TwoBodyMOIntsTransform> tform = tfactory->twobody_transform(
00141 MOIntsTransformFactory::StorageType_13,
00142 tlabel,
00143 intdescrs_bra[f]
00144 );
00145 transforms_bra.push_back(tform);
00146 }
00147 }
00148 }
00149 }
00150
00151
00152
00153
00154 Timer tim_gen_tensor_contract("Generic direct tensor contract");
00155 std::string label;
00156 {
00157 std::ostringstream oss_bra;
00158 oss_bra << "<" << space1_bra->id() << " " << space2_bra->id() << (antisymmetrize ? "||" : "|")
00159 << space1_intb->id() << " " << space2_intb->id() << ">";
00160 const std::string label_bra = oss_bra.str();
00161 std::ostringstream oss_ket;
00162 oss_ket << "<" << space1_ket->id() << " " << space2_ket->id() << (antisymmetrize ? "||" : "|")
00163 << space1_intk->id() << " " << space2_intk->id() << ">";
00164 const std::string label_ket = oss_ket.str();
00165 std::ostringstream oss;
00166 oss << "<" << space1_bra->id() << " " << space2_bra->id() << (antisymmetrize ? "||" : "|")
00167 << space1_ket->id() << " " << space2_ket->id() << "> = "
00168 << label_bra << " . " << label_ket << "^T";
00169 label = oss.str();
00170 }
00171 ExEnv::out0() << endl << indent
00172 << "Entered generic direct contraction (" << label << ")" << endl;
00173 ExEnv::out0() << incindent;
00174
00175
00176
00177
00178
00179
00180 Ref<OrbitalSpace> tspace1_bra = transforms_bra[0]->space1();
00181 Ref<OrbitalSpace> tspace2_bra = transforms_bra[0]->space3();
00182 Ref<OrbitalSpace> tspace1_intb = transforms_bra[0]->space2();
00183 Ref<OrbitalSpace> tspace2_intb = transforms_bra[0]->space4();
00184
00185 std::vector<unsigned int> map1_bra, map2_bra, map1_intb, map2_intb;
00186 {
00187 map1_bra = *tspace1_bra<<*space1_bra;
00188 map2_bra = *tspace2_bra<<*space2_bra;
00189 map1_intb = *tspace1_intb<<*space1_intb;
00190 map2_intb = *tspace2_intb<<*space2_intb;
00191 }
00192
00193 const unsigned int bratform_block_ncols = tspace2_intb->rank();
00194 const RefDiagSCMatrix evals1_bra = space1_bra->evals();
00195 const RefDiagSCMatrix evals2_bra = space2_bra->evals();
00196 const RefDiagSCMatrix evals1_ket = space1_ket->evals();
00197 const RefDiagSCMatrix evals2_ket = space2_ket->evals();
00198 const RefDiagSCMatrix evals1_intb = space1_intb->evals();
00199 const RefDiagSCMatrix evals2_intb = space2_intb->evals();
00200 const RefDiagSCMatrix evals1_intk = space1_intk->evals();
00201 const RefDiagSCMatrix evals2_intk = space2_intk->evals();
00202
00203
00204
00205 const SpinCase2 S = (alphabeta ? AlphaBeta : AlphaAlpha);
00206 SpinMOPairIter iterbra(space1_bra,(alphabeta ? space2_bra : space1_bra),S);
00207 SpinMOPairIter iterint(space1_intb,(alphabeta ? space2_intb : space1_intb),S);
00208
00209 const unsigned int nbra = iterbra.nij();
00210
00211 const unsigned int nint = iterint.nij();
00212
00213
00214
00215
00216
00217 unsigned int fbraoffset = 0;
00218 for(unsigned int fbra=0; fbra<nbrasets; ++fbra,fbraoffset+=nbra) {
00219 const unsigned int fbraint = fbra*nintsets+fint;
00220 Ref<TwoBodyMOIntsTransform> tformb = transforms_bra[fbraint];
00221 const Ref<TwoBodyIntDescr>& intdescrb = tformb->intdescr();
00222 const unsigned int intsetidx_bra = intdescrb->intset(tbint_type_bra);
00223
00224 Ref<R12IntsAcc> accumb = tformb->ints_acc();
00225
00226 if (accumb.null() || !accumb->is_committed()) {
00227 tformb->compute();
00228 accumb = tformb->ints_acc();
00229 }
00230 if (!accumb->is_active()) {
00231
00232 accumb->activate();
00233 }
00234
00235 }
00236
00237 RefSCMatrix Tcontr;
00238
00239 if (antisymmetrize && alphabeta) {
00240 Tcontr = T.kit()->matrix(new SCDimension(nbra*nbrasets),
00241 new SCDimension(nket*nketsets));
00242 Tcontr.assign(0.0);
00243 }
00244 else
00245 Tcontr = T;
00246
00247
00248 const unsigned int blksize_int = space1_intb->rank() * space2_intb->rank();
00249 double* T_ij = new double[blksize_int];
00250 double* T_kl = new double[blksize_int];
00251
00252
00253
00254
00255
00256
00257 for(unsigned int fint=0; fint<nintsets; ++fint) {
00258
00259 unsigned int fbraoffset = 0;
00260 for(unsigned int fbra=0; fbra<nbrasets; ++fbra,fbraoffset+=nbra) {
00261 const unsigned int fbraint = fbra*nintsets+fint;
00262 Ref<TwoBodyMOIntsTransform> tformb = transforms_bra[fbraint];
00263 const Ref<TwoBodyIntDescr>& intdescrb = tformb->intdescr();
00264 const unsigned int intsetidx_bra = intdescrb->intset(tbint_type_bra);
00265
00266 Ref<R12IntsAcc> accumb = tformb->ints_acc();
00267
00268 if (accumb.null() || !accumb->is_committed()) {
00269 tformb->compute();
00270 accumb = tformb->ints_acc();
00271 }
00272 if (!accumb->is_active()) {
00273
00274 accumb->activate();
00275 }
00276
00277 unsigned int fketoffset = 0;
00278 for(unsigned int fket=0; fket<nketsets; ++fket,fketoffset+=nket) {
00279 const unsigned int fketint = fket*nintsets+fint;
00280 Ref<TwoBodyMOIntsTransform> tformk = transforms_ket[fketint];
00281 const Ref<TwoBodyIntDescr>& intdescrk = tformk->intdescr();
00282 const unsigned int intsetidx_ket = intdescrk->intset(tbint_type_ket);
00283
00284 Ref<R12IntsAcc> accumk = tformk->ints_acc();
00285 if (accumk.null() || !accumk->is_committed()) {
00286 tformk->compute();
00287 accumk = tformk->ints_acc();
00288 }
00289 if (!accumk->is_active()) {
00290
00291 accumk->activate();
00292 }
00293
00294 if (debug_ >= DefaultPrintThresholds::diagnostics) {
00295 ExEnv::out0() << indent << "Using transforms "
00296 << tformb->name() << " and "
00297 << tformk->name() << std::endl;
00298 }
00299
00300
00301
00302 vector<int> proc_with_ints;
00303 const int nproc_with_ints = accumb->tasks_with_access(proc_with_ints);
00304 const int me = r12info()->msg()->me();
00305 const bool nket_ge_nevals = (nket >= nproc_with_ints);
00306
00307 if (accumb->has_access(me)) {
00308
00309 unsigned int ijkl = 0;
00310 for(iterbra.start(); iterbra; iterbra.next()) {
00311 const int ij = iterbra.ij();
00312
00313 bool fetch_ij_block = false;
00314 if (nket_ge_nevals) {
00315 fetch_ij_block = true;
00316 }
00317 else {
00318 const int first_ij_task = ijkl%nproc_with_ints;
00319 const int last_ij_task = (ijkl+nket-1)%nproc_with_ints;
00320
00321 if ( !(first_ij_task > proc_with_ints[me] && proc_with_ints[me] > last_ij_task) )
00322 fetch_ij_block = true;
00323 }
00324 if (!fetch_ij_block)
00325 continue;
00326
00327 const unsigned int i = iterbra.i();
00328 const unsigned int j = iterbra.j();
00329 const unsigned int ii = map1_bra[i];
00330 const unsigned int jj = map2_bra[j];
00331
00332 Timer tim_intsretrieve("MO ints retrieve");
00333 const double *ij_buf = accumb->retrieve_pair_block(ii,jj,intsetidx_bra);
00334 tim_intsretrieve.exit();
00335 if (debug_ >= DefaultPrintThresholds::allO2N2)
00336 ExEnv::outn() << indent << "task " << me << ": obtained ij blocks" << endl;
00337
00338 for(iterket.start(); iterket; iterket.next(),ijkl++) {
00339 const int kl = iterket.ij();
00340
00341 const int ijkl_proc = ijkl%nproc_with_ints;
00342 if (ijkl_proc != proc_with_ints[me])
00343 continue;
00344
00345 const unsigned int k = iterket.i();
00346 const unsigned int l = iterket.j();
00347 const unsigned int kk = map1_ket[k];
00348 const unsigned int ll = map2_ket[l];
00349
00350 if (debug_ >= DefaultPrintThresholds::allO2N2)
00351 ExEnv::outn() << indent << "task " << me << ": working on (i,j | k,l) = ("
00352 << i << "," << j << " | " << k << "," << l << ")" << endl;
00353 tim_intsretrieve.enter("MO ints retrieve");
00354 const double *kl_buf = accumk->retrieve_pair_block(kk,ll,intsetidx_ket);
00355 tim_intsretrieve.exit();
00356 if (debug_ >= DefaultPrintThresholds::allO2N2)
00357 ExEnv::outn() << indent << "task " << me << ": obtained kl blocks" << endl;
00358
00359
00360 memset(T_ij, 0, blksize_int*sizeof(double));
00361 memset(T_kl, 0, blksize_int*sizeof(double));
00362
00363 if (debug_ >= DefaultPrintThresholds::allO2N2) {
00364 ExEnv::out0() << indent << "i = " << i << " j = " << j << " k = " << k << " l = " << l
00365 << incindent << endl;
00366 }
00367
00368 for(iterint.start(); iterint; iterint.next()) {
00369 const unsigned int m = iterint.i();
00370 const unsigned int n = iterint.j();
00371 const int mn = iterint.ij();
00372 int MN_bra, MN_ket;
00373 {
00374 const unsigned int mm = map1_intb[m];
00375 const unsigned int nn = map2_intb[n];
00376 MN_bra = mm*bratform_block_ncols+nn;
00377 }
00378 {
00379 const unsigned int mm = map1_intk[m];
00380 const unsigned int nn = map2_intk[n];
00381 MN_ket = mm*kettform_block_ncols+nn;
00382 }
00383
00384 const double I_ijmn = ij_buf[MN_bra];
00385 const double I_klmn = kl_buf[MN_ket];
00386
00387 if (debug_ >= DefaultPrintThresholds::mostO6) {
00388 ExEnv::out0() << indent << " m = " << m << " n = " << n << endl;
00389 }
00390
00391 if (alphabeta) {
00392 if (debug_ >= DefaultPrintThresholds::mostO6) {
00393 ExEnv::out0() << indent << " <ij|mn> = " << I_ijmn << endl
00394 << indent << " <kl|mn> = " << I_klmn << endl;
00395 }
00396 const double T_ijmn = DataProcess_Bra::I2T(I_ijmn,i,j,m,n,
00397 evals1_bra,evals1_intb,evals2_bra,evals2_intb);
00398 const double T_klmn = DataProcess_Ket::I2T(I_klmn,k,l,m,n,
00399 evals1_ket,evals1_intk,evals2_ket,evals2_intk);
00400 if (debug_ >= DefaultPrintThresholds::mostO6) {
00401 ExEnv::out0() << indent << " <ij|T|mn> = " << T_ijmn << endl
00402 << indent << " <kl|T|mn> = " << T_klmn << endl;
00403 }
00404
00405 T_ij[mn] = T_ijmn;
00406 T_kl[mn] = T_klmn;
00407 }
00408 else {
00409
00410 int NM_bra, NM_ket;
00411 {
00412 const unsigned int mm = map21_intb[m];
00413 const unsigned int nn = map12_intb[n];
00414 NM_bra = nn*bratform_block_ncols+mm;
00415 }
00416 {
00417 const unsigned int mm = map21_intk[m];
00418 const unsigned int nn = map12_intk[n];
00419 NM_ket = nn*kettform_block_ncols+mm;
00420 }
00421
00422 const double I_ijnm = ij_buf[NM_bra];
00423 const double I_klnm = kl_buf[NM_ket];
00424
00425 if (debug_ >= DefaultPrintThresholds::mostO6) {
00426 ExEnv::out0() << " <ij|mn> = " << I_ijmn << endl
00427 << " <ij|nm> = " << I_ijnm << endl
00428 << " <kl|mn> = " << I_klmn << endl
00429 << " <kl|nm> = " << I_klnm << endl;
00430 }
00431
00432 const double T_ijmn = DataProcess_Bra::I2T(I_ijmn-I_ijnm,i,j,m,n,
00433 evals1_bra,evals1_intb,evals2_bra,evals2_intb);
00434 const double T_klmn = DataProcess_Ket::I2T(I_klmn-I_klnm,k,l,m,n,
00435 evals1_ket,evals1_intk,evals2_ket,evals2_intk);
00436 if (debug_ >= DefaultPrintThresholds::mostO6) {
00437 ExEnv::out0() << indent << " <ij|T|mn> = " << T_ijmn << endl
00438 << indent << " <kl|T|mn> = " << T_klmn << endl;
00439 }
00440 T_ij[mn] = T_ijmn;
00441 T_kl[mn] = T_klmn;
00442 }
00443
00444 }
00445
00446
00447 double T_ijkl = tpcontract->contract(T_ij,T_kl);
00448 if (debug_ >= DefaultPrintThresholds::allO2N2) {
00449 ExEnv::out0() << decindent << indent
00450 << " <ij|kl> = " << T_ijkl << endl;
00451 }
00452 T_ijkl = DataProcess_BraKet::I2T(T_ijkl,i,j,k,l,
00453 evals1_bra,evals1_ket,evals2_bra,evals2_ket);
00454 if (debug_ >= DefaultPrintThresholds::allO2N2) {
00455 ExEnv::out0() << indent << " <ij|T|kl> = " << T_ijkl << endl;
00456 }
00457 Tcontr.accumulate_element(ij+fbraoffset,kl+fketoffset,T_ijkl);
00458
00459 accumk->release_pair_block(kk,ll,intsetidx_ket);
00460
00461 }
00462
00463 if (fetch_ij_block)
00464 accumb->release_pair_block(ii,jj,intsetidx_bra);
00465
00466 }
00467 }
00468
00469
00470
00471
00472 if (accumb != accumk) {
00473
00474 accumk->deactivate();
00475 }
00476 }
00477
00478 accumb->deactivate();
00479 }
00480 }
00481
00482 if (antisymmetrize && alphabeta) {
00483
00484 symmetrize<false>(Tcontr,Tcontr,space1_bra,space1_ket);
00485 sc::antisymmetrize(T,Tcontr,space1_bra,space1_ket,true);
00486 Tcontr = 0;
00487 }
00488
00489 delete[] T_ij;
00490 delete[] T_kl;
00491
00492 ExEnv::out0() << decindent;
00493 ExEnv::out0() << indent << "Exited generic contraction (" << label << ")" << endl;
00494 tim_gen_tensor_contract.exit();
00495 }
00496
00497 }
00498
00499 #endif
00500