28 #ifndef _mpqc_src_lib_chemistry_qc_lcao_fockbuilder_h
29 #define _mpqc_src_lib_chemistry_qc_lcao_fockbuilder_h
32 #include <util/ref/ref.h>
33 #include <util/group/thread.h>
34 #include <util/misc/scexception.h>
35 #include <chemistry/qc/basis/gpetite.h>
36 #include <chemistry/qc/basis/symmint.h>
37 #include <chemistry/qc/lcao/fockbuild.h>
38 #include <chemistry/qc/lcao/clhfcontrib.h>
39 #include <chemistry/qc/lcao/hsoshfcontrib.h>
40 #include <chemistry/qc/lcao/moints_runtime.h>
41 #include <chemistry/qc/lcao/fockbuild_runtime.h>
51 return kit->symmmatrix(bradim);
60 return result->convert(original);
62 template <
typename T>
static void convert(
const value& result,
const T& original) {
71 return kit->matrix(bradim,ketdim);
76 if (transform_type == SCMatrix::NormalTransform)
77 result.accumulate_product(Ubra, original * Uket.
t());
79 result.accumulate_product(Ubra.
t(), original * Uket);
82 return result->convert(original);
84 template <
typename T>
static void convert(
const value& result,
const T& original) {
93 template <OneBodyIntCreator OpEval>
97 localints->set_basis(bas);
102 opmat_ao.assign(0.0);
105 opmat_ao.element_op(elemop);
110 pl->symmetrize(opmat_ao, opmat);
115 template <OneBodyIntCreator OpEval>
120 localints->set_basis(bas);
127 template <OneBodyIntCreator OpEval>
128 RefSCMatrix onebodyint_ao(
const Ref<GaussianBasisSet>& brabas,
129 const Ref<GaussianBasisSet>& ketbas,
130 const Ref<Integral>& integral) {
132 Ref<Integral> localints = integral->clone();
133 Ref<GPetiteList2> pl12 = GPetiteListFactory::plist2(brabas,ketbas);
134 localints->set_basis(brabas,ketbas);
135 Ref<OneBodyInt> ov_ints = (localints->*OpEval)();
138 RefSCMatrix sao(brabas->basisdim(), ketbas->basisdim(), brabas->matrixkit());
142 const Ref<GaussianBasisSet>& bs1 = brabas;
143 const Ref<GaussianBasisSet>& bs2 = ketbas;
144 const int nshell1 = bs1->nshell();
145 const int nshell2 = bs2->nshell();
146 for(
int sh1=0; sh1<nshell1; sh1++) {
147 const int bf1_offset = bs1->shell_to_function(sh1);
148 const int nbf1 = bs1->shell(sh1).nfunction();
150 for(
int sh2=0; sh2<nshell2; sh2++) {
151 const int bf2_offset = bs2->shell_to_function(sh2);
152 const int nbf2 = bs2->shell(sh2).nfunction();
154 ov_ints->compute_shell(sh1,sh2);
155 const double *ovintsptr = ov_ints->buffer();
157 int bf1_index = bf1_offset;
158 for(
int bf1=0; bf1<nbf1; bf1++, bf1_index++, ovintsptr+=nbf2) {
159 int bf2_index = bf2_offset;
160 const double *ptr = ovintsptr;
161 for(
int bf2=0; bf2<nbf2; bf2++, bf2_index++) {
163 sao.set_element(bf1_index, bf2_index, *(ptr++));
174 template <MultipoleOneBodyIntCreator OpEval>
175 void onebodyint_ao(
const Ref<GaussianBasisSet>& brabas,
176 const Ref<GaussianBasisSet>& ketbas,
177 const Ref<Integral>& integral,
const Ref<IntParamsOrigin>& multipole_origin,
178 std::vector<RefSCMatrix>& result) {
180 Ref<Integral> localints = integral->
clone();
181 Ref<GPetiteList2> pl12 = GPetiteListFactory::plist2(brabas,ketbas);
182 localints->set_basis(brabas,ketbas);
183 Ref<OneBodyInt> ob_ints = (localints->*OpEval)(multipole_origin);
186 const size_t nopers = result.size();
187 for(
int i=0; i<nopers; ++i) {
188 result[i] = brabas->matrixkit()->matrix(brabas->basisdim(), ketbas->basisdim());
189 result[i].assign(0.0);
192 const Ref<GaussianBasisSet>& bs1 = brabas;
193 const Ref<GaussianBasisSet>& bs2 = ketbas;
194 const int nshell1 = bs1->nshell();
195 const int nshell2 = bs2->nshell();
196 for(
int sh1=0; sh1<nshell1; sh1++) {
197 const int bf1_offset = bs1->shell_to_function(sh1);
198 const int nbf1 = bs1->shell(sh1).nfunction();
200 for(
int sh2=0; sh2<nshell2; sh2++) {
201 const int bf2_offset = bs2->shell_to_function(sh2);
202 const int nbf2 = bs2->shell(sh2).nfunction();
204 ob_ints->compute_shell(sh1,sh2);
205 const double *ovintsptr = ob_ints->buffer();
207 int bf1_index = bf1_offset;
208 for(
int bf1=0; bf1<nbf1; bf1++, bf1_index++, ovintsptr+=nopers*nbf2) {
209 int bf2_index = bf2_offset;
210 const double *ptr = ovintsptr;
211 for(
int bf2=0; bf2<nbf2; bf2++, bf2_index++) {
213 for(
size_t oper=0; oper<nopers; ++oper)
214 result[oper].set_element(bf1_index, bf2_index, *(ptr++));
223 template <OneBodyIntCreator OpEval>
224 RefSCMatrix onebodyint(
const Ref<GaussianBasisSet>& brabas,
225 const Ref<GaussianBasisSet>& ketbas,
226 const Ref<Integral>& integral) {
228 RefSCMatrix sao = onebodyint_ao<OpEval>(brabas, ketbas, integral);
229 Ref<Integral> braints = integral->clone(); braints->set_basis(brabas);
230 Ref<PetiteList> brapl = braints->petite_list();
231 Ref<Integral> ketints = integral->clone(); ketints->set_basis(ketbas);
232 Ref<PetiteList> ketpl = ketints->petite_list();
235 RefSCMatrix sao_blk = dynamic_cast<BlockedSCMatrix*>(sao.pointer());
236 if (sao_blk.null()) {
237 sao_blk = brabas->so_matrixkit()->matrix(brapl->AO_basisdim(),ketpl->AO_basisdim());
238 sao_blk->convert(sao);
241 if (brabas->molecule()->point_group()->order() == 1)
245 RefSCMatrix ssoao = brapl->aotoso().t() * sao_blk;
246 RefSCMatrix result = ssoao * ketpl->aotoso();
252 RefSymmSCMatrix
overlap(
const Ref<GaussianBasisSet>& bas,
253 const Ref<Integral>& integral);
255 RefSCMatrix
overlap(
const Ref<GaussianBasisSet>& brabs,
256 const Ref<GaussianBasisSet>& ketbs,
257 const Ref<Integral>& integral);
259 void edipole(
const Ref<GaussianBasisSet>& basis,
260 const Ref<Integral>& integral,
261 RefSymmSCMatrix& mu_x,
262 RefSymmSCMatrix& mu_y,
263 RefSymmSCMatrix& mu_z
266 RefSymmSCMatrix twobody_twocenter_coulomb(
const Ref<GaussianBasisSet>& bas,
267 const Ref<Integral>& integral);
269 RefSymmSCMatrix nonrelativistic(
const Ref<GaussianBasisSet>& bas,
270 const Ref<Integral>& integral);
272 RefSymmSCMatrix pauli(
const Ref<GaussianBasisSet>& bas,
273 const Ref<Integral>& integral);
275 RefSymmSCMatrix dk(
int dklev,
const Ref<GaussianBasisSet>& bs,
276 const Ref<GaussianBasisSet>& pbs,
277 const Ref<Integral>& integral);
279 RefSCMatrix coulomb(
const Ref<TwoBodyFourCenterMOIntsRuntime>& ints_rtime,
280 const Ref<OrbitalSpace>& occspace,
281 const Ref<OrbitalSpace>& braspace,
282 const Ref<OrbitalSpace>& ketspace);
283 RefSCMatrix exchange(
const Ref<TwoBodyFourCenterMOIntsRuntime>& ints_rtime,
284 const Ref<OrbitalSpace>& occspace,
285 const Ref<OrbitalSpace>& braspace,
286 const Ref<OrbitalSpace>& ketspace);
288 RefSCMatrix coulomb_df(
const Ref<DensityFittingInfo>& df_info,
289 const RefSymmSCMatrix& P,
290 const Ref<GaussianBasisSet>& brabs,
291 const Ref<GaussianBasisSet>& ketbs,
292 const Ref<GaussianBasisSet>& obs);
293 #ifdef MPQC_NEW_FEATURES
294 RefSCMatrix coulomb_df_local(
const Ref<DensityFittingInfo>& df_info,
295 const RefSymmSCMatrix& P,
296 const Ref<GaussianBasisSet>& brabs,
297 const Ref<GaussianBasisSet>& ketbs,
298 const Ref<GaussianBasisSet>& obs);
299 #endif // MPQC_NEW_FEATURES
300 RefSCMatrix exchange_df(
const Ref<DensityFittingInfo>& df_info,
301 const RefSymmSCMatrix& P,
303 const Ref<GaussianBasisSet>& brabs,
304 const Ref<GaussianBasisSet>& ketbs,
305 const Ref<GaussianBasisSet>& obs,
306 const Ref<FockBuildRuntime::PSqrtRegistry>& psqrtregistry);
307 #ifdef MPQC_NEW_FEATURES
308 RefSCMatrix exchange_df_local(
const Ref<DensityFittingInfo>& df_info,
309 const RefSymmSCMatrix& P,
311 const Ref<GaussianBasisSet>& brabs,
312 const Ref<GaussianBasisSet>& ketbs,
313 const Ref<GaussianBasisSet>& obs,
314 const Ref<FockBuildRuntime::PSqrtRegistry>& psqrtregistry);
315 #endif // MPQC_NEW_FEATURES
338 double accuracy = 1e-20) :
339 compute_F_(compute_F),
340 compute_J_(compute_J),
341 compute_K_(compute_K)
344 if (brabasis->equiv(ketbasis) != bra_eq_ket)
345 throw ProgrammingError(
"FockMatrixBuilder::FockMatrixBuilder -- inconsistent constructor and template arguments",
351 const bool openshell = openshelldensity;
353 fc =
new HSOSHFContribution(brabasis, ketbasis, densitybasis, std::string(
"replicated"));
355 fc->set_pmat(0, density);
356 fc->set_pmat(1, openshelldensity);
358 fc =
new CLHFContribution(brabasis, ketbasis, densitybasis, std::string(
"replicated"));
360 fc->set_pmat(0, density);
365 const bool really_compute_F = compute_F_ && !compute_J_ && !compute_K_;
366 const bool really_compute_J = !really_compute_F && compute_J_;
367 const bool really_compute_K = !really_compute_F && compute_K_;
371 ResultType G_ao_skel[2][3];
372 for(
int t=0; t<ntypes_; ++t) {
373 if (really_compute_J) {
374 G_ao_skel[t][0] = ResultFactory::create(brabasis->matrixkit(),brabasis->basisdim(),ketbasis->basisdim());
375 G_ao_skel[t][0].assign(0.0);
376 fc->set_jmat(t, G_ao_skel[t][0]);
378 if (really_compute_K) {
379 G_ao_skel[t][1] = ResultFactory::create(brabasis->matrixkit(),brabasis->basisdim(),ketbasis->basisdim());
380 G_ao_skel[t][1].assign(0.0);
381 fc->set_kmat(t, G_ao_skel[t][1]);
383 if (really_compute_F) {
384 G_ao_skel[t][2] = ResultFactory::create(brabasis->matrixkit(),brabasis->basisdim(),ketbasis->basisdim());
385 G_ao_skel[t][2].assign(0.0);
386 fc->set_fmat(t, G_ao_skel[t][2]);
390 const bool prefetch_blocks =
false;
392 fb_ =
new FockBuild(fd, fc, prefetch_blocks, brabasis, ketbasis, densitybasis, msg, thr, localints);
393 fb_->set_accuracy(accuracy);
394 fb_->set_compute_J(really_compute_J);
395 fb_->set_compute_K(really_compute_K);
399 localints->set_basis(brabasis);
401 localints->set_basis(ketbasis);
403 const int ng = pl->point_group()->char_table().order();
406 for(
int t=0; t<ntypes_; ++t) {
407 for(
int c=0; c<3; ++c) {
409 if (really_compute_J ==
false && c == 0)
continue;
410 if (really_compute_K ==
false && c == 1)
continue;
411 if (really_compute_F ==
false && c == 2)
continue;
413 if (c == 0 && t == 1)
continue;
417 if (ng == 1 || !bra_eq_ket) {
420 result_[t][c] = ResultFactory::create(brabasis->so_matrixkit(),brapl->AO_basisdim(),ketpl->AO_basisdim());
421 result_[t][c]->convert(G_ao_skel[t][c]);
424 G_ao_skel[t][c].scale(1.0/(
double)ng);
425 ResultType G_so = ResultFactory::create(brabasis->so_matrixkit(),brapl->SO_basisdim(),ketpl->SO_basisdim());
426 symmetrize(pl,localints,G_ao_skel[t][c],G_so);
432 result_[t][c] = ResultFactory::create(brabasis->so_matrixkit(),brapl->AO_basisdim(),ketpl->AO_basisdim());
438 if (c == 1) result_[t][1].scale(-1.0);
443 if (compute_F_ && !really_compute_F) {
445 result_[0][2] = result_[0][0] - result_[0][1];
447 result_[1][2] = result_[1][1].copy();
448 result_[1][2].scale(-1.0);
455 double nints()
const {
return builder()->contrib()->nint(); }
456 const ResultType& F(
unsigned int t = 0)
const {
457 MPQC_ASSERT(compute_F_ && t < ntypes_);
458 return result_[t][2];
460 const ResultType& J(
unsigned int t = 0)
const {
461 MPQC_ASSERT(compute_J_ && t < ntypes_ && t == 0);
462 return result_[t][0];
464 const ResultType& K(
unsigned int t = 0)
const {
465 MPQC_ASSERT(compute_K_ && t < ntypes_);
466 return result_[t][1];
468 ResultType F(SpinCase1 spin)
const {
472 return (spin == Alpha) ? F(0) + F(1) : F(0) - F(1);
475 ResultType K(SpinCase1 spin)
const {
479 return (spin == Alpha) ? K(0) + K(1) : K(0) - K(1);
490 ResultType result_[2][3];
507 compute_J_(compute_J),
508 compute_K_(compute_K),
509 compute_F_(compute_J && compute_K)
512 for(
int t=0; t<3; ++t) {
514 if (compute_J ==
false && t == 0)
continue;
515 if (compute_K ==
false && t == 1)
continue;
518 result_[t] = detail::coulomb(ints_rtime,occspace_A,braspace,ketspace);
519 if (*occspace_A == *occspace_B) {
520 result_[t].scale(2.0);
523 result_[t].accumulate( detail::coulomb(ints_rtime,occspace_B,braspace,ketspace) );
528 result_[t] = detail::exchange(ints_rtime,(spin == Alpha ? occspace_A : occspace_B),braspace,ketspace);
534 result_[2] = result_[0] - result_[1];
539 MPQC_ASSERT(compute_F_);
543 MPQC_ASSERT(compute_J_);
547 MPQC_ASSERT(compute_K_);
577 compute_J_(compute_J),
578 compute_K_(compute_K),
579 compute_F_(compute_F),
580 ntypes_(openshelldensity ? 2 : 1)
585 const bool really_compute_F = compute_F_;
586 const bool really_compute_J = compute_J_ || compute_F_;
587 const bool really_compute_K = compute_K_ || compute_F_;
589 for(
int t=0; t<ntypes_; ++t) {
590 const SpinCase1 spin = static_cast<SpinCase1>(t);
591 for(
int c=0; c<3; ++c) {
593 if (really_compute_J ==
false && c == 0)
continue;
594 if (really_compute_K ==
false && c == 1)
continue;
595 if (really_compute_F ==
false && c == 2)
continue;
597 if (c == 0 && t == 1)
continue;
600 if(df_info->params()->local_coulomb()) {
601 #ifdef MPQC_NEW_FEATURES
602 result_[0][c] = detail::coulomb_df_local(df_info, density, brabasis, ketbasis, densitybasis);
603 #else // MPQC_NEW_FEATURES
606 #endif // MPQC_NEW_FEATURES
609 result_[0][c] = detail::coulomb_df(df_info, density, brabasis, ketbasis, densitybasis);
615 if (openshelldensity) {
616 Pspin = (spin == Alpha) ? density + openshelldensity : density - openshelldensity;
620 Pspin = density.copy();
621 spincase = AnySpinCase1;
624 if(df_info->params()->local_exchange()) {
625 #ifdef MPQC_NEW_FEATURES
626 result_[t][c] = detail::exchange_df_local(df_info, Pspin, spincase, brabasis, ketbasis, densitybasis,
628 #else // MPQC_NEW_FEATURES
631 #endif // MPQC_NEW_FEATURES
634 result_[t][c] = detail::exchange_df(df_info, Pspin, spincase, brabasis, ketbasis, densitybasis,
639 result_[t][2] = result_[0][0] - result_[t][1];
646 const ResultType& F(
unsigned int t = 0)
const {
647 MPQC_ASSERT(compute_F_ && t < ntypes_);
648 return result_[t][2];
650 const ResultType& J(
unsigned int t = 0)
const {
651 MPQC_ASSERT(compute_J_ && t < ntypes_);
652 return result_[t][0];
654 const ResultType& K(
unsigned int t = 0)
const {
655 MPQC_ASSERT(compute_K_ && t < ntypes_);
656 return result_[t][1];
662 return (spin == Alpha) ? F(0) : F(1);
670 return (spin == Alpha) ? K(0) : K(1);
689 typedef enum { NonRelativistic, Pauli, DK1, DK2 } OneBodyHamiltonianType;
699 double accuracy = 1e-12)
701 if (brabasis->equiv(ketbasis) != bra_eq_ket)
702 throw ProgrammingError(
"OneBodyFockMatrixBuilder::OneBodyFockMatrixBuilder -- inconsistent constructor and template arguments",
707 const bool bs1_eq_bs2 = bra_eq_ket;
712 if (type == DK1 || type == DK2) {
715 p_basis = p_basis + hcore_basis;
720 case NonRelativistic: hsymm = detail::nonrelativistic(hcore_basis,integral);
break;
721 case Pauli: hsymm = detail::pauli(hcore_basis,integral);
break;
726 hsymm = detail::dk(dklev, hcore_basis, p_basis, integral);
735 localints->set_basis(hcore_basis,hcore_basis);
740 localints->set_basis(brabasis);
742 localints->set_basis(ketbasis);
747 result_ = ResultFactory::create(brabasis->so_matrixkit(),braaodim,ketaodim);
748 ResultFactory::convert(result_,hsymm_ao);
751 RefSCMatrix result_rect = brabasis->so_matrixkit()->matrix(braaodim,ketaodim);
752 RefSCMatrix hrect_ao = brabasis->so_matrixkit()->matrix(hsymm_ao.dim(),hsymm_ao.dim());
753 hrect_ao.assign(0.0);
754 hrect_ao.accumulate(hsymm_ao);
764 const int nfblock1 = bs1_to_hbs.
nfblock();
765 const int nfblock2 = bs2_to_hbs.
nfblock();
766 for (
int rb = 0; rb < nfblock1; ++rb) {
768 const int rf_end1 = rf_start1 + bs1_to_hbs.
fblock_size(rb) - 1;
770 const int rf_start12 = bs1_to_hbs.
map_function(rf_start1);
773 for (
int cb = 0; cb < nfblock2; ++cb) {
775 const int cf_end2 = cf_start2 + bs2_to_hbs.
fblock_size(cb) - 1;
777 const int cf_start12 =
782 result_rect.assign_subblock(hrect_ao, rf_start1, rf_end1, cf_start2, cf_end2,
783 rf_start12, cf_start12);
787 result_ = ResultFactory::create(brabasis->so_matrixkit(),braaodim,ketaodim);
788 ResultFactory::convert(result_,result_rect);
794 const ResultType& result()
const {
return result_; }
804 #endif // end of header guard