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 #include <cmath>
00033 #include <util/misc/regtime.h>
00034 #include <chemistry/qc/mbptr12/pairiter.h>
00035 #include <chemistry/qc/mbptr12/utils.h>
00036 #include <chemistry/qc/mbptr12/utils.impl.h>
00037 #include <chemistry/qc/mbptr12/r12int_eval.h>
00038 #include <chemistry/qc/mbptr12/print.h>
00039
00040 #ifndef _chemistry_qc_mbptr12_computetbinttensor_h
00041 #define _chemistry_qc_mbptr12_computetbinttensor_h
00042
00043 namespace sc {
00044
00045 template <typename DataProcess,
00046 bool CorrFactorInBra,
00047 bool CorrFactorInKet>
00048 void
00049 R12IntEval::compute_tbint_tensor(RefSCMatrix& T,
00050 TwoBodyInt::tbint_type tbint_type,
00051 const Ref<OrbitalSpace>& space1_bra,
00052 const Ref<OrbitalSpace>& space1_ket,
00053 const Ref<OrbitalSpace>& space2_bra,
00054 const Ref<OrbitalSpace>& space2_ket,
00055 bool antisymmetrize,
00056 const std::vector<std::string>& transform_keys)
00057 {
00058
00059 const bool part1_strong_equiv_part2 = (space1_bra==space2_bra && space1_ket==space2_ket);
00060 const bool part1_weak_equiv_part2 = (space1_bra->rank()==space2_bra->rank() && space1_ket->rank()==space2_ket->rank());
00061
00062 const bool correct_semantics = (antisymmetrize && part1_weak_equiv_part2) ||
00063 !antisymmetrize;
00064 if (!correct_semantics)
00065 throw ProgrammingError("R12IntEval::compute_tbint_tensor_() -- incorrect call semantics",
00066 __FILE__,__LINE__);
00067
00068
00069 const bool alphabeta = !(antisymmetrize && part1_strong_equiv_part2);
00070
00071 const bool CorrFactorInBraKet = CorrFactorInBra && CorrFactorInKet;
00072
00073 const unsigned int nbrasets = (CorrFactorInBra ? corrfactor()->nfunctions() : 1);
00074 const unsigned int nketsets = (CorrFactorInKet ? corrfactor()->nfunctions() : 1);
00075 const unsigned int nsets = (CorrFactorInBraKet ? -1 : nbrasets*nketsets);
00076
00077
00078 typedef std::vector< Ref<TwoBodyMOIntsTransform> > tformvec;
00079 const size_t num_tforms = transform_keys.size();
00080 tformvec transforms(num_tforms);
00081 for(unsigned int t=0; t<num_tforms; ++t) {
00082 transforms[t] = r12info()->moints_runtime()->get(transform_keys[t]);
00083 }
00084
00085 Timer tim_generic_tensor("Generic tensor");
00086 std::ostringstream oss;
00087 oss << "<" << space1_bra->id() << " " << space2_bra->id() << (antisymmetrize ? "||" : "|")
00088 << space1_ket->id() << " " << space2_ket->id() << ">";
00089 const std::string label = oss.str();
00090 ExEnv::out0() << endl << indent
00091 << "Entered generic tensor (" << label << ") evaluator" << endl;
00092 ExEnv::out0() << incindent;
00093
00094
00095
00096
00097 Ref<OrbitalSpace> tspace1_bra = transforms[0]->space1();
00098 Ref<OrbitalSpace> tspace1_ket = transforms[0]->space2();
00099 Ref<OrbitalSpace> tspace2_bra = transforms[0]->space3();
00100 Ref<OrbitalSpace> tspace2_ket = transforms[0]->space4();
00101
00102
00103 std::vector<unsigned int> map1_bra, map1_ket, map2_bra, map2_ket;
00104
00105 std::vector<unsigned int> map12_ket;
00106
00107 std::vector<unsigned int> map21_ket;
00108 map1_bra = *tspace1_bra<<*space1_bra;
00109 map1_ket = *tspace1_ket<<*space1_ket;
00110 map2_bra = *tspace2_bra<<*space2_bra;
00111 map2_ket = *tspace2_ket<<*space2_ket;
00112 if (!alphabeta) {
00113 if (tspace1_ket == tspace2_ket) {
00114 map12_ket = map1_ket;
00115 map21_ket = map2_ket;
00116 }
00117 else {
00118 map12_ket = *tspace1_ket<<*space2_ket;
00119 map21_ket = *tspace2_ket<<*space1_ket;
00120 }
00121 }
00122
00123 const unsigned int tblock_ncols = tspace2_ket->rank();
00124 const RefDiagSCMatrix evals1_bra = space1_bra->evals();
00125 const RefDiagSCMatrix evals1_ket = space1_ket->evals();
00126 const RefDiagSCMatrix evals2_bra = space2_bra->evals();
00127 const RefDiagSCMatrix evals2_ket = space2_ket->evals();
00128
00129
00130
00131 const SpinCase2 S = (alphabeta ? AlphaBeta : AlphaAlpha);
00132 SpinMOPairIter iterbra(space1_bra,space2_bra,S);
00133 SpinMOPairIter iterket(space1_ket,space2_ket,S);
00134
00135 const unsigned int nbra = iterbra.nij();
00136
00137 const unsigned int nket = iterket.nij();
00138
00139 RefSCMatrix Tresult;
00140
00141 if (antisymmetrize && alphabeta) {
00142 Tresult = T.kit()->matrix(new SCDimension(nbra*nbrasets),
00143 new SCDimension(nket*nketsets));
00144 Tresult.assign(0.0);
00145 }
00146 else
00147 Tresult = T;
00148
00149 unsigned int fbraket = 0;
00150 unsigned int fbraoffset = 0;
00151 for(unsigned int fbra=0; fbra<nbrasets; ++fbra,fbraoffset+=nbra) {
00152
00153 unsigned int fketoffset = 0;
00154 for(unsigned int fket=0; fket<nketsets; ++fket,fketoffset+=nket,++fbraket) {
00155
00156 Ref<TwoBodyMOIntsTransform> tform = transforms[fbraket];
00157 const Ref<TwoBodyIntDescr>& intdescr = tform->intdescr();
00158 const unsigned int intsetidx = intdescr->intset(tbint_type);
00159
00160 if (debug_ > DefaultPrintThresholds::diagnostics)
00161 ExEnv::out0() << indent << "Using transform " << tform->name() << std::endl;
00162
00163 tform->compute();
00164 Ref<R12IntsAcc> accum = tform->ints_acc();
00165
00166
00167 vector<int> proc_with_ints;
00168 const int nproc_with_ints = accum->tasks_with_access(proc_with_ints);
00169 const int me = r12info()->msg()->me();
00170
00171 if (accum->has_access(me)) {
00172 for(iterbra.start(); iterbra; iterbra.next()) {
00173 const int ij = iterbra.ij();
00174
00175 const int ij_proc = ij%nproc_with_ints;
00176 if (ij_proc != proc_with_ints[me])
00177 continue;
00178
00179 const unsigned int i = iterbra.i();
00180 const unsigned int j = iterbra.j();
00181 const unsigned int ii = map1_bra[i];
00182 const unsigned int jj = map2_bra[j];
00183
00184 if (debug_ > DefaultPrintThresholds::allO2N2)
00185 ExEnv::outn() << indent << "task " << me << ": working on (i,j) = " << i << "," << j << " " << endl;
00186 Timer tim_intsretrieve("MO ints retrieve");
00187 const double *ij_buf = accum->retrieve_pair_block(ii,jj,intsetidx);
00188 tim_intsretrieve.exit();
00189 if (debug_ > DefaultPrintThresholds::allO2N2)
00190 ExEnv::outn() << indent << "task " << me << ": obtained ij blocks" << endl;
00191
00192 for(iterket.start(); iterket; iterket.next()) {
00193 const unsigned int a = iterket.i();
00194 const unsigned int b = iterket.j();
00195 const unsigned int aa = map1_ket[a];
00196 const unsigned int bb = map2_ket[b];
00197 const int AB = aa*tblock_ncols+bb;
00198 const int ab = iterket.ij();
00199
00200 const double I_ijab = ij_buf[AB];
00201
00202 if (alphabeta) {
00203 if (debug_ > DefaultPrintThresholds::allO2N2) {
00204 ExEnv::out0() << "i = " << i << " j = " << j << " a = " << a << " b = " << b
00205 << " <ij|ab> = " << I_ijab << endl;
00206 }
00207 const double T_ijab = DataProcess::I2T(I_ijab,i,j,a,b,evals1_bra,evals1_ket,evals2_bra,evals2_ket);
00208 Tresult.accumulate_element(ij+fbraoffset,ab+fketoffset,T_ijab);
00209 }
00210 else {
00211 const int aa = map21_ket[a];
00212 const int bb = map12_ket[b];
00213 const int BA = bb*tblock_ncols+aa;
00214 const double I_ijba = ij_buf[BA];
00215 if (debug_ > DefaultPrintThresholds::allO2N2) {
00216 ExEnv::out0() << "i = " << i << " j = " << j << " a = " << a << " b = " << b
00217 << " <ij|ab> = " << I_ijab << " <ij|ba> = " << I_ijba << endl;
00218 }
00219 const double I_anti = I_ijab - I_ijba;
00220 const double T_ijab = DataProcess::I2T(I_anti,i,j,a,b,evals1_bra,evals1_ket,evals2_bra,evals2_ket);
00221 Tresult.accumulate_element(ij+fbraoffset,ab+fketoffset,T_ijab);
00222 }
00223
00224 }
00225 accum->release_pair_block(ii,jj,intsetidx);
00226
00227 }
00228 }
00229
00230 }
00231 }
00232
00233 if (antisymmetrize && alphabeta) {
00234
00235 symmetrize<false>(Tresult,Tresult,space1_bra,space1_ket);
00236 sc::antisymmetrize(T,Tresult,space1_bra,space1_ket,true);
00237 Tresult = 0;
00238 }
00239
00240 ExEnv::out0() << decindent;
00241 ExEnv::out0() << indent << "Exited generic tensor (" << label << ") evaluator" << endl;
00242 tim_generic_tensor.exit();
00243 }
00244
00246 namespace ManyBodyTensors {
00247
00248 enum Sign {
00249 Minus = -1,
00250 Plus = +1
00251 };
00252
00254 template <Sign sign = Plus>
00255 class Apply_Identity {
00256 public:
00257 static double I2T(double I, int i1, int i3, int i2, int i4,
00258 const RefDiagSCMatrix& evals1,
00259 const RefDiagSCMatrix& evals2,
00260 const RefDiagSCMatrix& evals3,
00261 const RefDiagSCMatrix& evals4)
00262 {
00263 if (sign == Plus)
00264 return I;
00265 else
00266 return -I;
00267 }
00268 };
00269
00271 template <Sign sign = Plus>
00272 class Apply_H0minusE0 {
00273 public:
00274 static double I2T(double I, int i1, int i3, int i2, int i4,
00275 const RefDiagSCMatrix& evals1,
00276 const RefDiagSCMatrix& evals2,
00277 const RefDiagSCMatrix& evals3,
00278 const RefDiagSCMatrix& evals4)
00279 {
00280 const double ediff = (- evals1(i1) - evals3(i3) + evals2(i2) + evals4(i4));
00281 if (sign == Plus)
00282 return I*ediff;
00283 else
00284 return -I*ediff;
00285 }
00286 };
00287
00289 template <Sign sign = Plus>
00290 class Apply_Inverse_H0minusE0 {
00291 public:
00292 static double I2T(double I, int i1, int i3, int i2, int i4,
00293 const RefDiagSCMatrix& evals1,
00294 const RefDiagSCMatrix& evals2,
00295 const RefDiagSCMatrix& evals3,
00296 const RefDiagSCMatrix& evals4)
00297 {
00298 const double ediff = (- evals1(i1) - evals3(i3) + evals2(i2) + evals4(i4));
00299 if (sign == Plus)
00300 return I/ediff;
00301 else
00302 return -I/ediff;
00303 }
00304 };
00305
00309 template <Sign sign = Plus>
00310 class Apply_Inverse_Sqrt_H0minusE0 {
00311 public:
00312 static double I2T(double I, int i1, int i3, int i2, int i4,
00313 const RefDiagSCMatrix& evals1,
00314 const RefDiagSCMatrix& evals2,
00315 const RefDiagSCMatrix& evals3,
00316 const RefDiagSCMatrix& evals4)
00317 {
00318 const double ediff = (- evals1(i1) - evals3(i3) + evals2(i2) + evals4(i4));
00319 if (sign == Plus)
00320 return I/std::sqrt(std::fabs(ediff));
00321 else
00322 return -I/std::sqrt(std::fabs(ediff));
00323 }
00324 };
00325
00326 typedef Apply_Identity<Plus> I_to_T;
00327 typedef Apply_Identity<Minus> I_to_mT;
00328 typedef Apply_Inverse_Sqrt_H0minusE0<Plus> ERI_to_S2;
00329 typedef Apply_Inverse_H0minusE0<Minus> ERI_to_T2;
00330 }
00331
00332 }
00333
00334 #endif
00335