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 implementation
00030 #endif
00031
00032 #ifndef _mpqc_src_lib_chemistry_qc_mbptr12_fockbuilder_h
00033 #define _mpqc_src_lib_chemistry_qc_mbptr12_fockbuilder_h
00034
00035 #include <cassert>
00036 #include <util/ref/ref.h>
00037 #include <util/group/thread.h>
00038 #include <util/class/scexception.h>
00039 #include <chemistry/qc/basis/gpetite.h>
00040 #include <chemistry/qc/scf/fockbuild.h>
00041 #include <chemistry/qc/scf/clhfcontrib.h>
00042 #include <chemistry/qc/scf/hsoshfcontrib.h>
00043 #include <chemistry/qc/mbptr12/moints_runtime.h>
00044
00045 namespace sc {
00046
00047 namespace detail {
00048 template<bool bra_eq_ket> struct FockMatrixType;
00049 template<> struct FockMatrixType<true> {
00050 typedef RefSymmSCMatrix value;
00051 struct Factory {
00052 static value create(const Ref<SCMatrixKit>& kit, const RefSCDimension& bradim, const RefSCDimension& ketdim) {
00053 return kit->symmmatrix(bradim);
00054 }
00055 static void transform(const value& result, const value& original,
00056 const RefSCMatrix& Ubra, const RefSCMatrix& Uket,
00057 SCMatrix::Transform transform_type = SCMatrix::NormalTransform) {
00058 result.assign(0.0);
00059 result.accumulate_transform(Ubra,original,transform_type);
00060 }
00061 static void convert(const value& result, const value& original) {
00062 return result->convert(original);
00063 }
00064 template <typename T> static void convert(const value& result, const T& original) {
00065 abort();
00066 }
00067 };
00068 };
00069 template<> struct FockMatrixType<false> {
00070 typedef RefSCMatrix value;
00071 struct Factory {
00072 static value create(const Ref<SCMatrixKit>& kit, const RefSCDimension& bradim, const RefSCDimension& ketdim) {
00073 return kit->matrix(bradim,ketdim);
00074 }
00075 static void transform(const value& result, const value& original,
00076 const RefSCMatrix& Ubra, const RefSCMatrix& Uket,
00077 SCMatrix::Transform transform_type = SCMatrix::NormalTransform) {
00078 if (transform_type == SCMatrix::NormalTransform)
00079 result.accumulate_product(Ubra, original * Uket.t());
00080 else
00081 result.accumulate_product(Ubra.t(), original * Uket);
00082 }
00083 static void convert(const value& result, const value& original) {
00084 return result->convert(original);
00085 }
00086 template <typename T> static void convert(const value& result, const T& original) {
00087 abort();
00088 }
00089 };
00090 };
00091
00092
00093 RefSymmSCMatrix nonrelativistic(const Ref<GaussianBasisSet>& bas,
00094 const Ref<Integral>& integral);
00095 RefSymmSCMatrix pauli(const Ref<GaussianBasisSet>& bas,
00096 const Ref<Integral>& integral);
00097 RefSymmSCMatrix dk(int dklev, const Ref<GaussianBasisSet>& bs,
00098 const Ref<GaussianBasisSet>& pbs,
00099 const Ref<Integral>& integral);
00100
00101 RefSCMatrix coulomb(const Ref<MOIntsRuntime>& ints_rtime,
00102 const Ref<OrbitalSpace>& occspace,
00103 const Ref<OrbitalSpace>& braspace,
00104 const Ref<OrbitalSpace>& ketspace);
00105 RefSCMatrix exchange(const Ref<MOIntsRuntime>& ints_rtime,
00106 const Ref<OrbitalSpace>& occspace,
00107 const Ref<OrbitalSpace>& braspace,
00108 const Ref<OrbitalSpace>& ketspace);
00109
00110 }
00111
00112
00114 template<bool bra_eq_ket> class TwoBodyFockMatrixBuilder: public RefCount {
00115
00116 public:
00117
00118 typedef typename detail::FockMatrixType<bra_eq_ket>::value ResultType;
00119 typedef typename detail::FockMatrixType<bra_eq_ket>::Factory ResultFactory;
00120
00121 TwoBodyFockMatrixBuilder(bool compute_F,
00122 bool compute_J,
00123 bool compute_K,
00124 const Ref<GaussianBasisSet>& brabasis,
00125 const Ref<GaussianBasisSet>& ketbasis,
00126 const Ref<GaussianBasisSet>& densitybasis,
00127 const RefSymmSCMatrix& density,
00128 const RefSymmSCMatrix& openshelldensity,
00129 const Ref<Integral>& integral,
00130 const Ref<MessageGrp>& msg,
00131 const Ref<ThreadGrp>& thr,
00132 double accuracy = 1e-12) :
00133 compute_F_(compute_F),
00134 compute_J_(compute_J),
00135 compute_K_(compute_K)
00136 {
00137
00138 if (brabasis->equiv(ketbasis) != bra_eq_ket)
00139 throw ProgrammingError("FockMatrixBuilder::FockMatrixBuilder -- inconsistent constructor and template arguments",
00140 __FILE__, __LINE__);
00141
00142 Ref<Integral> localints = integral->clone();
00143
00144 Ref<FockContribution> fc;
00145 const bool openshell = openshelldensity.nonnull();
00146 if (openshell) {
00147 fc = new HSOSHFContribution(brabasis, ketbasis, densitybasis, std::string("replicated"));
00148 ntypes_ = 2;
00149 fc->set_pmat(0, density);
00150 fc->set_pmat(1, openshelldensity);
00151 } else {
00152 fc = new CLHFContribution(brabasis, ketbasis, densitybasis, std::string("replicated"));
00153 ntypes_ = 1;
00154 fc->set_pmat(0, density);
00155 }
00156
00157
00158
00159 const bool really_compute_F = compute_F_ && !compute_J_ && !compute_K_;
00160 const bool really_compute_J = !really_compute_F;
00161 const bool really_compute_K = !really_compute_F;
00162
00163
00164
00165 ResultType G_ao_skel[2][3];
00166 for(int t=0; t<ntypes_; ++t) {
00167 if (really_compute_J) {
00168 G_ao_skel[t][0] = ResultFactory::create(brabasis->matrixkit(),brabasis->basisdim(),ketbasis->basisdim());
00169 G_ao_skel[t][0].assign(0.0);
00170 fc->set_jmat(t, G_ao_skel[t][0]);
00171 }
00172 if (really_compute_K) {
00173 G_ao_skel[t][1] = ResultFactory::create(brabasis->matrixkit(),brabasis->basisdim(),ketbasis->basisdim());
00174 G_ao_skel[t][1].assign(0.0);
00175 fc->set_kmat(t, G_ao_skel[t][1]);
00176 }
00177 if (really_compute_F) {
00178 G_ao_skel[t][2] = ResultFactory::create(brabasis->matrixkit(),brabasis->basisdim(),ketbasis->basisdim());
00179 G_ao_skel[t][2].assign(0.0);
00180 fc->set_fmat(t, G_ao_skel[t][2]);
00181 }
00182 }
00183
00184 const bool prefetch_blocks = false;
00185 Ref<FockDistribution> fd = new FockDistribution;
00186 fb_ = new FockBuild(fd, fc, prefetch_blocks, brabasis, ketbasis, densitybasis, msg, thr, localints);
00187 fb_->set_accuracy(accuracy);
00188 fb_->build();
00189
00190 Ref<GPetiteList2> pl = GPetiteListFactory::plist2(brabasis,ketbasis);
00191 localints->set_basis(brabasis);
00192 Ref<PetiteList> brapl = localints->petite_list();
00193 localints->set_basis(ketbasis);
00194 Ref<PetiteList> ketpl = localints->petite_list();
00195 const int ng = pl->point_group()->char_table().order();
00196
00198 for(int t=0; t<ntypes_; ++t) {
00199 for(int c=0; c<3; ++c) {
00200
00201 if (really_compute_J == false && c == 0) continue;
00202 if (really_compute_K == false && c == 1) continue;
00203 if (really_compute_F == false && c == 2) continue;
00204
00205 if (c == 0 && t == 1) continue;
00206
00207
00208
00209 if (ng == 1 || !bra_eq_ket) {
00210 RefSCDimension braaodim = brapl->AO_basisdim();
00211 RefSCDimension ketaodim = ketpl->AO_basisdim();
00212 result_[t][c] = ResultFactory::create(brabasis->so_matrixkit(),brapl->AO_basisdim(),ketpl->AO_basisdim());
00213 result_[t][c]->convert(G_ao_skel[t][c]);
00214 }
00215 else {
00216 G_ao_skel[t][c].scale(1.0/(double)ng);
00217 ResultType G_so = ResultFactory::create(brabasis->so_matrixkit(),brapl->SO_basisdim(),ketpl->SO_basisdim());
00218 symmetrize(pl,localints,G_ao_skel[t][c],G_so);
00219 G_ao_skel[t][c] = 0;
00220
00221
00222 RefSCDimension braaodim = brapl->AO_basisdim();
00223 RefSCDimension ketaodim = ketpl->AO_basisdim();
00224 result_[t][c] = ResultFactory::create(brabasis->so_matrixkit(),brapl->AO_basisdim(),ketpl->AO_basisdim());
00225 ResultFactory::transform(result_[t][c], G_so, brapl->sotoao(), ketpl->sotoao(), SCMatrix::TransposeTransform);
00226
00227 }
00228
00229
00230 if (c == 1) result_[t][1].scale(-1.0);
00231
00232 }
00233 }
00234
00235 if (compute_F_ && !really_compute_F)
00236 for(int t=0; t<ntypes_; ++t) {
00237 result_[t][2] = result_[t][0] - result_[t][1];
00238 }
00239
00240 }
00241
00242 const Ref<FockBuild>& builder() const { return fb_; }
00243 double nints() const { return builder()->contrib()->nint(); }
00244 const ResultType& F(unsigned int t = 0) const {
00245 assert(compute_F_ && t < ntypes_);
00246 return result_[t][2];
00247 }
00248 const ResultType& J(unsigned int t = 0) const {
00249 assert(compute_J_ && t < ntypes_);
00250 return result_[t][0];
00251 }
00252 const ResultType& K(unsigned int t = 0) const {
00253 assert(compute_K_ && t < ntypes_);
00254 return result_[t][1];
00255 }
00256 ResultType F(SpinCase1 spin) const {
00257 if (ntypes_ == 1)
00258 return F(0);
00259 else {
00260 return (spin == Alpha) ? F(0) + F(1) : F(0) - F(1);
00261 }
00262 }
00263 ResultType K(SpinCase1 spin) const {
00264 if (ntypes_ == 1)
00265 return K(0);
00266 else {
00267 return (spin == Alpha) ? K(0) + K(1) : K(0) - K(1);
00268 }
00269 }
00270
00271 private:
00272
00273 Ref<FockBuild> fb_;
00274 bool compute_J_;
00275 bool compute_K_;
00276 bool compute_F_;
00277 int ntypes_;
00278 ResultType result_[2][3];
00279
00280 };
00281
00283 class TwoBodyFockTransformBuilder: public RefCount {
00284
00285 public:
00286
00287 TwoBodyFockTransformBuilder(bool compute_J,
00288 bool compute_K,
00289 SpinCase1 spin,
00290 const Ref<OrbitalSpace>& braspace,
00291 const Ref<OrbitalSpace>& ketspace,
00292 const Ref<OrbitalSpace>& occspace_A,
00293 const Ref<OrbitalSpace>& occspace_B,
00294 const Ref<MOIntsRuntime>& ints_rtime) :
00295 compute_J_(compute_J),
00296 compute_K_(compute_K),
00297 compute_F_(compute_J && compute_K)
00298 {
00299
00300 for(int t=0; t<3; ++t) {
00301
00302 if (compute_J == false && t == 0) continue;
00303 if (compute_K == false && t == 1) continue;
00304
00305 if (t == 0) {
00306 result_[t] = detail::coulomb(ints_rtime,occspace_A,braspace,ketspace);
00307 if (*occspace_A == *occspace_B) {
00308 result_[t].scale(2.0);
00309 }
00310 else {
00311 result_[t].accumulate( detail::coulomb(ints_rtime,occspace_B,braspace,ketspace) );
00312 }
00313 }
00314
00315 if (t == 1) {
00316 result_[t] = detail::exchange(ints_rtime,(spin == Alpha ? occspace_A : occspace_B),braspace,ketspace);
00317 }
00318
00319 }
00320
00321 if (compute_F_)
00322 result_[2] = result_[0] - result_[1];
00323
00324 }
00325
00326 const RefSCMatrix& F() const {
00327 assert(compute_F_);
00328 return result_[2];
00329 }
00330 const RefSCMatrix& J() const {
00331 assert(compute_J_);
00332 return result_[0];
00333 }
00334 const RefSCMatrix& K() const {
00335 assert(compute_K_);
00336 return result_[1];
00337 }
00338
00339 private:
00340
00341 bool compute_J_;
00342 bool compute_K_;
00343 bool compute_F_;
00344 RefSCMatrix result_[3];
00345
00346 };
00347
00349 template<bool bra_eq_ket> class OneBodyFockMatrixBuilder: public RefCount {
00350
00351 public:
00352
00353 typedef enum { NonRelativistic, Pauli, DK1, DK2 } OneBodyHamiltonianType;
00354
00355 typedef typename detail::FockMatrixType<bra_eq_ket>::value ResultType;
00356 typedef typename detail::FockMatrixType<bra_eq_ket>::Factory ResultFactory;
00357
00358 OneBodyFockMatrixBuilder(OneBodyHamiltonianType type,
00359 const Ref<GaussianBasisSet>& brabasis,
00360 const Ref<GaussianBasisSet>& ketbasis,
00361 const Ref<GaussianBasisSet>& pbasis,
00362 const Ref<Integral>& integral,
00363 double accuracy = 1e-12)
00364 {
00365 if (brabasis->equiv(ketbasis) != bra_eq_ket)
00366 throw ProgrammingError("OneBodyFockMatrixBuilder::OneBodyFockMatrixBuilder -- inconsistent constructor and template arguments",
00367 __FILE__, __LINE__);
00368
00369 const Ref<GaussianBasisSet>& bs1 = brabasis;
00370 const Ref<GaussianBasisSet>& bs2 = ketbasis;
00371 const bool bs1_eq_bs2 = bra_eq_ket;
00372
00373 Ref<GaussianBasisSet> hcore_basis;
00374 Ref<GaussianBasisSetSum> bs1_plus_bs2;
00375 if (bs1_eq_bs2) {
00376 hcore_basis = bs1;
00377 }
00378 else {
00379 bs1_plus_bs2 = new GaussianBasisSetSum(bs1,bs2);
00380 hcore_basis = bs1_plus_bs2->bs12();
00381 }
00382
00383 Ref<GaussianBasisSet> p_basis = pbasis;
00384 if (type == DK1 || type == DK2) {
00385
00386
00387 p_basis = p_basis + hcore_basis;
00388 }
00389
00390 RefSymmSCMatrix hsymm;
00391 switch (type) {
00392 case NonRelativistic: hsymm = detail::nonrelativistic(hcore_basis,integral); break;
00393 case Pauli: hsymm = detail::pauli(hcore_basis,integral); break;
00394
00395 int dklev;
00396 case DK1: dklev = 1;
00397 case DK2: dklev = 2;
00398 hsymm = detail::dk(dklev, hcore_basis, p_basis, integral);
00399 break;
00400
00401 default:
00402 throw ProgrammingError("Unrecognized Hamiltonian type",__FILE__,__LINE__);
00403 }
00404
00405
00406 Ref<Integral> localints = integral->clone();
00407 localints->set_basis(hcore_basis,hcore_basis);
00408 Ref<PetiteList> hcore_pl = localints->petite_list();
00409 RefSymmSCMatrix hsymm_ao = hcore_pl->to_AO_basis(hsymm);
00410 hsymm = 0;
00411
00412 localints->set_basis(brabasis);
00413 Ref<PetiteList> brapl = localints->petite_list();
00414 localints->set_basis(ketbasis);
00415 Ref<PetiteList> ketpl = localints->petite_list();
00416 RefSCDimension braaodim = brapl->AO_basisdim();
00417 RefSCDimension ketaodim = ketpl->AO_basisdim();
00418 if (bs1_eq_bs2) {
00419 result_ = ResultFactory::create(brabasis->so_matrixkit(),braaodim,ketaodim);
00420 ResultFactory::convert(result_,hsymm_ao);
00421 }
00422 else {
00423 RefSCMatrix result_rect = brabasis->so_matrixkit()->matrix(braaodim,ketaodim);
00424 RefSCMatrix hrect_ao = brabasis->so_matrixkit()->matrix(hsymm_ao.dim(),hsymm_ao.dim());
00425 hrect_ao.assign(0.0);
00426 hrect_ao.accumulate(hsymm_ao);
00427
00428
00429
00430
00431
00432
00433
00434 const int nbf = hcore_basis->nbasis();
00435 const int nfblock = bs1_plus_bs2->nfblock();
00436 for(int rb=0; rb<nfblock; ++rb) {
00437 const int rf_start12 = bs1_plus_bs2->fblock_to_function(rb);
00438 if (bs1_plus_bs2->function_to_basis(rf_start12) != 1)
00439 continue;
00440 const int rf_end12 = rf_start12 + bs1_plus_bs2->fblock_size(rb) - 1;
00441
00442 const int rf_start1 = bs1_plus_bs2->function12_to_function(rf_start12);
00443 const int rf_end1 = bs1_plus_bs2->function12_to_function(rf_end12);
00444
00445 for(int cb=0; cb<nfblock; ++cb) {
00446 const int cf_start12 = bs1_plus_bs2->fblock_to_function(cb);
00447 if (bs1_plus_bs2->function_to_basis(cf_start12) != 2)
00448 continue;
00449 const int cf_end12 = cf_start12 + bs1_plus_bs2->fblock_size(cb) - 1;
00450
00451 const int cf_start2 = bs1_plus_bs2->function12_to_function(cf_start12);
00452 const int cf_end2 = bs1_plus_bs2->function12_to_function(cf_end12);
00453
00454
00455 result_rect.assign_subblock(hrect_ao, rf_start1, rf_end1, cf_start2, cf_end2, rf_start12, cf_start12);
00456 }
00457 }
00458
00459 result_ = ResultFactory::create(brabasis->so_matrixkit(),braaodim,ketaodim);
00460 ResultFactory::convert(result_,result_rect);
00461
00462 }
00463
00464 }
00465
00466 const ResultType& result() const { return result_; }
00467
00468 private:
00469
00470 ResultType result_;
00471
00472 };
00473
00474 }
00475
00476 #endif // end of header guard
00477
00478
00479
00480
00481