// // r12int_eval.cc // // Copyright (C) 2004 Edward Valeev // // Author: Edward Valeev // Maintainer: EV // // This file is part of the SC Toolkit. // // The SC Toolkit is free software; you can redistribute it and/or modify // it under the terms of the GNU Library General Public License as published by // the Free Software Foundation; either version 2, or (at your option) // any later version. // // The SC Toolkit is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with the SC Toolkit; see the file COPYING.LIB. If not, write to // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. // // The U.S. Government is granted a limited license as per AL 91-7. // #ifdef __GNUG__ #pragma implementation #endif #include #include #include #include #include #include #include using namespace std; using namespace sc; #define TEST_FOCK 0 #define NOT_INCLUDE_DIAGONAL_VXB_CONTIBUTIONS 0 inline int max(int a,int b) { return (a > b) ? a : b;} /*----------------- R12IntEval -----------------*/ static ClassDesc R12IntEval_cd( typeid(R12IntEval),"R12IntEval",1,"virtual public SavableState", 0, 0, 0); R12IntEval::R12IntEval(const Ref& r12info, bool gbc, bool ebc, LinearR12::ABSMethod abs_method, LinearR12::StandardApproximation stdapprox, bool follow_ks_ebcfree) : r12info_(r12info), gbc_(gbc), ebc_(ebc), abs_method_(abs_method), stdapprox_(stdapprox), spinadapted_(false), include_mp1_(false), follow_ks_ebcfree_(follow_ks_ebcfree), debug_(0), evaluated_(false) { int nocc_act = r12info_->nocc_act(); int nvir_act = r12info_->nvir_act(); dim_ij_aa_ = new SCDimension((nocc_act*(nocc_act-1))/2); dim_ij_ab_ = new SCDimension(nocc_act*nocc_act); dim_ij_s_ = new SCDimension((nocc_act*(nocc_act+1))/2); dim_ij_t_ = dim_ij_aa_; dim_ab_aa_ = new SCDimension((nvir_act*(nvir_act-1))/2); dim_ab_ab_ = new SCDimension(nvir_act*nvir_act); Ref local_matrix_kit = new LocalSCMatrixKit(); Vaa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ij_aa_); Vab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ij_ab_); Xaa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ij_aa_); Xab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ij_ab_); Baa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ij_aa_); Bab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ij_ab_); if (ebc_ == false) { Aaa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ab_aa_); Aab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ab_ab_); if (follow_ks_ebcfree_) { Ac_aa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ab_aa_); Ac_ab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ab_ab_); } T2aa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ab_aa_); T2ab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ab_ab_); Raa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ab_aa_); Rab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ab_ab_); } emp2pair_aa_ = local_matrix_kit->vector(dim_ij_aa_); emp2pair_ab_ = local_matrix_kit->vector(dim_ij_ab_); init_intermeds_(); init_tforms_(); } R12IntEval::R12IntEval(StateIn& si) : SavableState(si) { int gbc; si.get(gbc); gbc_ = (bool) gbc; int ebc; si.get(ebc); ebc_ = (bool) ebc; int absmethod; si.get(absmethod); abs_method_ = (LinearR12::ABSMethod) absmethod; int stdapprox; si.get(stdapprox); stdapprox_ = (LinearR12::StandardApproximation) stdapprox; int follow_ks_ebcfree; si.get(follow_ks_ebcfree); follow_ks_ebcfree_ = static_cast(follow_ks_ebcfree); r12info_ << SavableState::restore_state(si); dim_ij_aa_ << SavableState::restore_state(si); dim_ij_ab_ << SavableState::restore_state(si); dim_ij_s_ << SavableState::restore_state(si); dim_ij_t_ << SavableState::restore_state(si); dim_ab_aa_ << SavableState::restore_state(si); dim_ab_ab_ << SavableState::restore_state(si); Ref local_matrix_kit = new LocalSCMatrixKit(); Vaa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ij_aa_); Vab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ij_ab_); Xaa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ij_aa_); Xab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ij_ab_); Baa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ij_aa_); Bab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ij_ab_); if (ebc_ == false) { Aaa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ab_aa_); Aab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ab_ab_); if (follow_ks_ebcfree_) { Ac_aa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ab_aa_); Ac_ab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ab_ab_); } T2aa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ab_aa_); T2ab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ab_ab_); Raa_ = local_matrix_kit->matrix(dim_ij_aa_,dim_ab_aa_); Rab_ = local_matrix_kit->matrix(dim_ij_ab_,dim_ab_ab_); } emp2pair_aa_ = local_matrix_kit->vector(dim_ij_aa_); emp2pair_ab_ = local_matrix_kit->vector(dim_ij_ab_); Vaa_.restore(si); Vab_.restore(si); Xaa_.restore(si); Xab_.restore(si); Baa_.restore(si); Bab_.restore(si); if (ebc_ == false) { Aaa_.restore(si); Aab_.restore(si); Ac_aa_.restore(si); Ac_ab_.restore(si); T2aa_.restore(si); T2ab_.restore(si); Raa_.restore(si); Rab_.restore(si); } emp2pair_aa_.restore(si); emp2pair_ab_.restore(si); int num_tforms; si.get(num_tforms); for(int t=0; t tform; tform << SavableState::restore_state(si); tform_map_[tform_name] = tform; } int spinadapted; si.get(spinadapted); spinadapted_ = (bool) spinadapted; int evaluated; si.get(evaluated); evaluated_ = (bool) evaluated; si.get(debug_); init_tforms_(); } R12IntEval::~R12IntEval() { r12info_ = 0; dim_ij_aa_ = 0; dim_ij_ab_ = 0; dim_ij_s_ = 0; dim_ij_t_ = 0; dim_ab_aa_ = 0; dim_ab_ab_ = 0; } void R12IntEval::save_data_state(StateOut& so) { so.put((int)gbc_); so.put((int)ebc_); so.put((int)abs_method_); so.put((int)stdapprox_); so.put((int)follow_ks_ebcfree_); SavableState::save_state(r12info_.pointer(),so); SavableState::save_state(dim_ij_aa_.pointer(),so); SavableState::save_state(dim_ij_ab_.pointer(),so); SavableState::save_state(dim_ij_s_.pointer(),so); SavableState::save_state(dim_ij_t_.pointer(),so); SavableState::save_state(dim_ab_aa_.pointer(),so); SavableState::save_state(dim_ab_ab_.pointer(),so); Vaa_.save(so); Vab_.save(so); Xaa_.save(so); Xab_.save(so); Baa_.save(so); Bab_.save(so); if (ebc_ == false) { Aaa_.save(so); Aab_.save(so); Ac_aa_.save(so); Ac_ab_.save(so); T2aa_.save(so); T2ab_.save(so); Raa_.save(so); Rab_.save(so); } emp2pair_aa_.save(so); emp2pair_ab_.save(so); int num_tforms = tform_map_.size(); so.put(num_tforms); TformMap::iterator first_tform = tform_map_.begin(); TformMap::iterator last_tform = tform_map_.end(); for(TformMap::iterator t=first_tform; t!=last_tform; t++) { so.put((*t).first); SavableState::save_state((*t).second.pointer(),so); } so.put((int)spinadapted_); so.put((int)evaluated_); so.put(debug_); } void R12IntEval::obsolete() { evaluated_ = false; // make all transforms obsolete TformMap::iterator first_tform = tform_map_.begin(); TformMap::iterator last_tform = tform_map_.end(); for(TformMap::iterator t=first_tform; t!=last_tform; t++) { (*t).second->obsolete(); } init_intermeds_(); } void R12IntEval::include_mp1(bool include_mp1) { include_mp1_ = include_mp1; }; void R12IntEval::set_debug(int debug) { if (debug >= 0) { debug_ = debug; r12info_->set_debug_level(debug_); }}; void R12IntEval::set_dynamic(bool dynamic) { r12info_->set_dynamic(dynamic); }; void R12IntEval::set_print_percent(double pp) { r12info_->set_print_percent(pp); }; void R12IntEval::set_memory(size_t nbytes) { r12info_->set_memory(nbytes); }; Ref R12IntEval::r12info() const { return r12info_; }; RefSCDimension R12IntEval::dim_oo_aa() const { return dim_ij_aa_; }; RefSCDimension R12IntEval::dim_oo_ab() const { return dim_ij_ab_; }; RefSCDimension R12IntEval::dim_oo_s() const { return dim_ij_s_; }; RefSCDimension R12IntEval::dim_oo_t() const { return dim_ij_t_; }; RefSCDimension R12IntEval::dim_vv_aa() const { return dim_ab_aa_; }; RefSCDimension R12IntEval::dim_vv_ab() const { return dim_ab_ab_; }; RefSCMatrix R12IntEval::V_aa() { compute(); return Vaa_; } RefSCMatrix R12IntEval::X_aa() { compute(); return Xaa_; } RefSymmSCMatrix R12IntEval::B_aa() { compute(); // Extract lower triangle of the matrix Ref kit = Baa_.kit(); RefSymmSCMatrix Baa = kit->symmmatrix(Baa_.rowdim()); int naa = Baa_.nrow(); double* baa = new double[naa*naa]; Baa_.convert(baa); const double* baa_ptr = baa; for(int i=0; i kit = Bab_.kit(); RefSymmSCMatrix Bab = kit->symmmatrix(Bab_.rowdim()); int nab = Bab_.nrow(); double* bab = new double[nab*nab]; Bab_.convert(bab); const double* bab_ptr = bab; for(int i=0; iobs_space()->evals(); }; void R12IntEval::checkpoint_() const { int me = r12info_->msg()->me(); Wavefunction* wfn = r12info_->wfn(); if (me == 0 && wfn->if_to_checkpoint()) { StateOutBin stateout(wfn->checkpoint_file()); SavableState::save_state(wfn,stateout); ExEnv::out0() << indent << "Checkpointed the wave function" << endl; } } void R12IntEval::init_tforms_() { Ref tfactory = r12info_->tfactory(); tfactory->set_ints_method((MOIntsTransformFactory::StoreMethod)r12info_->ints_method()); const std::string ipjq_name = "(ip|jq)"; Ref ipjq_tform = tform_map_[ipjq_name]; if (ipjq_tform.null()) { tfactory->set_spaces(r12info_->act_occ_space(),r12info_->obs_space(), r12info_->act_occ_space(),r12info_->obs_space()); ipjq_tform = tfactory->twobody_transform_13(ipjq_name); tform_map_[ipjq_name] = ipjq_tform; tform_map_[ipjq_name]->set_num_te_types(3); } const std::string iajb_name = "(ia|jb)"; Ref iajb_tform = tform_map_[iajb_name]; if (iajb_tform.null()) { tfactory->set_spaces(r12info_->act_occ_space(),r12info_->act_vir_space(), r12info_->act_occ_space(),r12info_->act_vir_space()); iajb_tform = tfactory->twobody_transform_13(iajb_name); tform_map_[iajb_name] = iajb_tform; tform_map_[iajb_name]->set_num_te_types(3); } const std::string imja_name = "(im|ja)"; Ref imja_tform = tform_map_[imja_name]; if (imja_tform.null()) { tfactory->set_spaces(r12info_->act_occ_space(),r12info_->occ_space(), r12info_->act_occ_space(),r12info_->act_vir_space()); imja_tform = tfactory->twobody_transform_13(imja_name); tform_map_[imja_name] = imja_tform; tform_map_[imja_name]->set_num_te_types(4); } const std::string imjn_name = "(im|jn)"; Ref imjn_tform = tform_map_[imjn_name]; if (imjn_tform.null()) { tfactory->set_spaces(r12info_->act_occ_space(),r12info_->occ_space(), r12info_->act_occ_space(),r12info_->occ_space()); imjn_tform = tfactory->twobody_transform_13(imjn_name); tform_map_[imjn_name] = imjn_tform; tform_map_[imjn_name]->set_num_te_types(3); } const std::string imjy_name = "(im|jy)"; Ref imjy_tform = tform_map_[imjy_name]; if (imjy_tform.null()) { tfactory->set_spaces(r12info_->act_occ_space(),r12info_->occ_space(), r12info_->act_occ_space(),r12info_->ribs_space()); imjy_tform = tfactory->twobody_transform_13(imjy_name); tform_map_[imjy_name] = imjy_tform; tform_map_[imjy_name]->set_num_te_types(4); } iajb_tform = tform_map_[iajb_name]; imjn_tform = tform_map_[imjn_name]; ipjq_tform = tform_map_[ipjq_name]; } Ref R12IntEval::get_tform_(const std::string& tform_name) { TformMap::const_iterator tform_iter = tform_map_.find(tform_name); TwoBodyMOIntsTransform* tform = (*tform_iter).second.pointer(); if (tform == NULL) { std::string errmsg = "R12IntEval::get_tform_() -- transform " + tform_name + " is not known"; throw std::runtime_error(errmsg.c_str()); } tform->compute(); return tform; } void R12IntEval::init_intermeds_() { if (r12info_->msg()->me() == 0) { #if NOT_INCLUDE_DIAGONAL_VXB_CONTIBUTIONS Vaa_->assign(0.0); Vab_->assign(0.0); Baa_->assign(0.0); Bab_->assign(0.0); #else Vaa_->unit(); Vab_->unit(); Baa_->unit(); Bab_->unit(); #endif } else { Vaa_.assign(0.0); Vab_.assign(0.0); Baa_.assign(0.0); Bab_.assign(0.0); } if (ebc_ == false) { Aaa_.assign(0.0); Aab_.assign(0.0); if (follow_ks_ebcfree_) { Ac_aa_.assign(0.0); Ac_ab_.assign(0.0); } T2aa_.assign(0.0); T2ab_.assign(0.0); Raa_.assign(0.0); Rab_.assign(0.0); } Xaa_.assign(0.0); Xab_.assign(0.0); //r2_contrib_to_X_orig_(); #if !NOT_INCLUDE_DIAGONAL_VXB_CONTIBUTIONS r2_contrib_to_X_new_(); #endif emp2pair_aa_.assign(0.0); emp2pair_ab_.assign(0.0); } /// Compute RefSCMatrix R12IntEval::compute_r2_(const Ref& space1, const Ref& space2) { /*----------------------------------------------------- Compute overlap, dipole, quadrupole moment integrals -----------------------------------------------------*/ RefSCMatrix S_11, MX_11, MY_11, MZ_11, MXX_11, MYY_11, MZZ_11; r12info_->compute_multipole_ints(space1, space1, MX_11, MY_11, MZ_11, MXX_11, MYY_11, MZZ_11); r12info_->compute_overlap_ints(space1, space1, S_11); RefSCMatrix S_12, MX_12, MY_12, MZ_12, MXX_12, MYY_12, MZZ_12; if (space1 == space2) { S_12 = S_11; MX_12 = MX_11; MY_12 = MY_11; MZ_12 = MZ_11; MXX_12 = MXX_11; MYY_12 = MYY_11; MZZ_12 = MZZ_11; } else { r12info_->compute_multipole_ints(space1, space2, MX_12, MY_12, MZ_12, MXX_12, MYY_12, MZZ_12); r12info_->compute_overlap_ints(space1, space2, S_12); } if (debug_) ExEnv::out0() << indent << "Computed overlap and multipole moment integrals" << endl; const int nproc = r12info_->msg()->n(); const int me = r12info_->msg()->me(); const int n1 = space1->rank(); const int n2 = space2->rank(); const int n12 = n1*n2; const int n1112 = n1*n1*n12; double* r2_array = new double[n1112]; memset(r2_array,0,n1112*sizeof(double)); int ij = 0; double* ijkl_ptr = r2_array; for(int i=0; iget_element(i,k) + MYY_11->get_element(i,k) + MZZ_11->get_element(i,k)); double r1r1_jl = -1.0*(MXX_12->get_element(j,l) + MYY_12->get_element(j,l) + MZZ_12->get_element(j,l)); double r1r2_ijkl = MX_11->get_element(i,k)*MX_12->get_element(j,l) + MY_11->get_element(i,k)*MY_12->get_element(j,l) + MZ_11->get_element(i,k)*MZ_12->get_element(j,l); double S_ik = S_11.get_element(i,k); double S_jl = S_12.get_element(j,l); double R2_ijkl = r1r1_ik * S_jl + r1r1_jl * S_ik - 2.0*r1r2_ijkl; *ijkl_ptr = R2_ijkl; } } r12info_->msg()->sum(r2_array,n1112); MOPairIterFactory pair_factory; RefSCDimension dim_ij = pair_factory.scdim_ab(space1,space1); RefSCDimension dim_kl = pair_factory.scdim_ab(space1,space2); Ref local_matrix_kit = new LocalSCMatrixKit(); RefSCMatrix R2 = local_matrix_kit->matrix(dim_ij, dim_kl); R2.assign(r2_array); delete[] r2_array; return R2; } void R12IntEval::r2_contrib_to_X_orig_() { /*--------------------------------------------------------------- Compute dipole and quadrupole moment integrals in act MO basis ---------------------------------------------------------------*/ RefSCMatrix MX, MY, MZ, MXX, MYY, MZZ; r12info_->compute_multipole_ints(r12info_->act_occ_space(),r12info_->act_occ_space(),MX,MY,MZ,MXX,MYY,MZZ); if (debug_) ExEnv::out0() << indent << "Computed multipole moment integrals" << endl; const int nproc = r12info_->msg()->n(); const int me = r12info_->msg()->me(); SpatialMOPairIter_eq ij_iter(r12info_->act_occ_space()); SpatialMOPairIter_eq kl_iter(r12info_->act_occ_space()); for(kl_iter.start();int(kl_iter);kl_iter.next()) { const int kl = kl_iter.ij(); int kl_proc = kl%nproc; if (kl_proc != me) continue; const int k = kl_iter.i(); const int l = kl_iter.j(); const int kl_aa = kl_iter.ij_aa(); const int kl_ab = kl_iter.ij_ab(); const int lk_ab = kl_iter.ij_ba(); for(ij_iter.start();int(ij_iter);ij_iter.next()) { const int i = ij_iter.i(); const int j = ij_iter.j(); const int ij_aa = ij_iter.ij_aa(); const int ij_ab = ij_iter.ij_ab(); const int ji_ab = ij_iter.ij_ba(); /*---------------------------------- Compute (r12)^2 contribution to X ----------------------------------*/ double r1r1_ik = -1.0*(MXX->get_element(i,k) + MYY->get_element(i,k) + MZZ->get_element(i,k)); double r1r1_il = -1.0*(MXX->get_element(i,l) + MYY->get_element(i,l) + MZZ->get_element(i,l)); double r1r1_jk = -1.0*(MXX->get_element(j,k) + MYY->get_element(j,k) + MZZ->get_element(j,k)); double r1r1_jl = -1.0*(MXX->get_element(j,l) + MYY->get_element(j,l) + MZZ->get_element(j,l)); double r1r2_ijkl = MX->get_element(i,k)*MX->get_element(j,l) + MY->get_element(i,k)*MY->get_element(j,l) + MZ->get_element(i,k)*MZ->get_element(j,l); double r1r2_ijlk = MX->get_element(i,l)*MX->get_element(j,k) + MY->get_element(i,l)*MY->get_element(j,k) + MZ->get_element(i,l)*MZ->get_element(j,k); double delta_ik = (i==k ? 1.0 : 0.0); double delta_il = (i==l ? 1.0 : 0.0); double delta_jk = (j==k ? 1.0 : 0.0); double delta_jl = (j==l ? 1.0 : 0.0); double Xab_ijkl = r1r1_ik * delta_jl + r1r1_jl * delta_ik - 2.0*r1r2_ijkl; Xab_.accumulate_element(ij_ab,kl_ab,Xab_ijkl); if (ij_ab != ji_ab) { double Xab_jikl = r1r1_jk * delta_il + r1r1_il * delta_jk - 2.0*r1r2_ijlk; Xab_.accumulate_element(ji_ab,kl_ab,Xab_jikl); } if (kl_ab != lk_ab) { double Xab_ijlk = r1r1_il * delta_jk + r1r1_jk * delta_il - 2.0*r1r2_ijlk; Xab_.accumulate_element(ij_ab,lk_ab,Xab_ijlk); } if (ij_ab != ji_ab && kl_ab != lk_ab) { double Xab_jilk = r1r1_ik * delta_jl + r1r1_jl * delta_ik - 2.0*r1r2_ijkl; Xab_.accumulate_element(ji_ab,lk_ab,Xab_jilk); } if (ij_aa != -1 && kl_aa != -1) { double Xaa_ijkl = r1r1_ik * delta_jl + r1r1_jl * delta_ik - 2.0*r1r2_ijkl - r1r1_jk * delta_il - r1r1_il * delta_jk + 2.0*r1r2_ijlk; Xaa_.accumulate_element(ij_aa,kl_aa,Xaa_ijkl); } } } } void R12IntEval::r2_contrib_to_X_new_() { unsigned int me = r12info_->msg()->me(); // compute r_{12}^2 operator in act.occ.pair/act.occ.pair basis RefSCMatrix R2 = compute_r2_(r12info_->act_occ_space(),r12info_->act_occ_space()); if (me != 0) return; Xab_.accumulate(R2); SpatialMOPairIter_eq ij_iter(r12info_->act_occ_space()); SpatialMOPairIter_eq kl_iter(r12info_->act_occ_space()); for(kl_iter.start();int(kl_iter);kl_iter.next()) { const int kl_aa = kl_iter.ij_aa(); if (kl_aa == -1) continue; const int kl_ab = kl_iter.ij_ab(); for(ij_iter.start();int(ij_iter);ij_iter.next()) { const int ij_aa = ij_iter.ij_aa(); const int ij_ab = ij_iter.ij_ab(); const int ji_ab = ij_iter.ij_ba(); if (ij_aa != -1) { double Xaa_ijkl = R2.get_element(ij_ab,kl_ab) - R2.get_element(ji_ab,kl_ab); Xaa_.accumulate_element(ij_aa,kl_aa,Xaa_ijkl); } } } } void R12IntEval::form_focc_space_() { // compute the Fock matrix between the complement and all occupieds and // create the new Fock-weighted space if (focc_space_.null()) { Ref occ_space = r12info_->occ_space(); Ref ribs_space = r12info_->ribs_space(); RefSCMatrix F_ri_o = fock_(occ_space,ribs_space,occ_space); if (debug_ > 1) F_ri_o.print("Fock matrix (RI-BS/occ.)"); focc_space_ = new MOIndexSpace("Fock-weighted occupied MOs sorted by energy", occ_space, ribs_space->coefs()*F_ri_o, ribs_space->basis()); } } void R12IntEval::form_factocc_space_() { // compute the Fock matrix between the complement and active occupieds and // create the new Fock-weighted space if (factocc_space_.null()) { Ref occ_space = r12info_->occ_space(); Ref act_occ_space = r12info_->act_occ_space(); Ref ribs_space = r12info_->ribs_space(); RefSCMatrix F_ri_ao = fock_(occ_space,ribs_space,act_occ_space); if (debug_ > 1) F_ri_ao.print("Fock matrix (RI-BS/act.occ.)"); factocc_space_ = new MOIndexSpace("Fock-weighted active occupied MOs sorted by energy", act_occ_space, ribs_space->coefs()*F_ri_ao, ribs_space->basis()); } } void R12IntEval::form_canonvir_space_() { // Create a complement space to all occupieds // Fock operator is diagonal in this space if (canonvir_space_.null()) { if (r12info_->basis_vir()->equiv(r12info_->basis())) { canonvir_space_ = r12info_->vir_space(); return; } const Ref mo_space = r12info_->mo_space(); Ref vir_space = r12info_->vir_space_symblk(); RefSCMatrix F_vir = fock_(r12info_->occ_space(),vir_space,vir_space); int nrow = vir_space->rank(); double* F_full = new double[nrow*nrow]; double* F_lowtri = new double [nrow*(nrow+1)/2]; F_vir->convert(F_full); int ij = 0; for(int row=0; rowkit()); F_vir_lt->assign(F_lowtri); F_vir = 0; delete[] F_full; delete[] F_lowtri; Ref canonvir_space_symblk = new MOIndexSpace("Virt. MOs symmetry-blocked", vir_space, vir_space->coefs()*F_vir_lt.eigvecs(), vir_space->basis()); RefDiagSCMatrix F_vir_evals = F_vir_lt.eigvals(); canonvir_space_ = new MOIndexSpace("Virt. MOs sorted by energy", canonvir_space_symblk->coefs(), canonvir_space_symblk->basis(), canonvir_space_symblk->integral(), F_vir_evals, 0, 0, MOIndexSpace::energy); } } const int R12IntEval::tasks_with_ints_(const Ref ints_acc, vector& map_to_twi) { int nproc = r12info_->msg()->n(); // Compute the number of tasks that have full access to the integrals // and split the work among them int nproc_with_ints = 0; for(int proc=0;prochas_access(proc)) nproc_with_ints++; map_to_twi.resize(nproc); int count = 0; for(int proc=0;prochas_access(proc)) { map_to_twi[proc] = count; count++; } else map_to_twi[proc] = -1; ExEnv::out0() << indent << "Computing intermediates on " << nproc_with_ints << " processors" << endl; return nproc_with_ints; } void R12IntEval::compute() { if (evaluated_) return; if (r12info_->basis_vir()->equiv(r12info_->basis())) { obs_contrib_to_VXB_gebc_vbseqobs_(); if (debug_ > 1) { Vaa_.print("Alpha-alpha V(OBS) contribution"); Vab_.print("Alpha-beta V(OBS) contribution"); Xaa_.print("Alpha-alpha X(OBS) contribution"); Xab_.print("Alpha-beta X(OBS) contribution"); Baa_.print("Alpha-alpha B(OBS) contribution"); Bab_.print("Alpha-beta B(OBS) contribution"); } if (r12info_->basis() != r12info_->basis_ri()) abs1_contrib_to_VXB_gebc_(); if (debug_ > 1) { Vaa_.print("Alpha-alpha V(OBS+ABS) contribution"); Vab_.print("Alpha-beta V(OBS+ABS) contribution"); Xaa_.print("Alpha-alpha X(OBS+ABS) contribution"); Xab_.print("Alpha-beta X(OBS+ABS) contribution"); Baa_.print("Alpha-alpha B(OBS+ABS) contribution"); Bab_.print("Alpha-beta B(OBS+ABS) contribution"); } } else { contrib_to_VXB_gebc_vbsneqobs_(); compute_dualEmp2_(); if (include_mp1_) compute_dualEmp1_(); } #if TEST_FOCK if (!evaluated_) { RefSCMatrix F = fock_(r12info_->occ_space(),r12info_->obs_space(),r12info_->obs_space()); F.print("Fock matrix in OBS"); r12info_->obs_space()->evals().print("OBS eigenvalues"); r12info_->ribs_space()->coefs().print("Orthonormal RI-BS"); RefSCMatrix S_ri; r12info_->compute_overlap_ints(r12info_->ribs_space(),r12info_->ribs_space(),S_ri); S_ri.print("Overlap in RI-BS"); RefSCMatrix F_ri = fock_(r12info_->occ_space(),r12info_->ribs_space(),r12info_->ribs_space()); F_ri.print("Fock matrix in RI-BS"); RefSymmSCMatrix F_ri_symm = F_ri.kit()->symmmatrix(F_ri.rowdim()); int nrow = F_ri.rowdim().n(); for(int r=0; rocc_space(),r12info_->obs_space(),r12info_->ribs_space()); F_obs_ri.print("Fock matrix in OBS/RI-BS"); } #endif if (!ebc_) { // These functions assume that virtuals are expanded in the same basis // as the occupied orbitals if (!r12info_->basis_vir()->equiv(r12info_->basis())) throw std::runtime_error("R12IntEval::compute() -- ebc=false is only supported when basis_vir == basis"); compute_A_simple_(); Aaa_.scale(2.0); Aab_.scale(2.0); if (follow_ks_ebcfree_) { compute_A_via_commutator_(); Ac_aa_.scale(2.0); Ac_ab_.scale(2.0); } compute_T2_(); AT2_contrib_to_V_(); compute_R_(); AR_contrib_to_B_(); } if (!gbc_) { // These functions assume that virtuals are expanded in the same basis // as the occupied orbitals if (!r12info_->basis_vir()->equiv(r12info_->basis())) throw std::runtime_error("R12IntEval::compute() -- gbc=false is only supported when basis_vir == basis"); compute_B_gbc_1_(); if (debug_ > 1) { Baa_.print("Alpha-alpha B(OBS+ABS+GBC1) contribution"); Bab_.print("Alpha-beta B(OBS+ABS+GBC1) contribution"); } compute_B_gbc_2_(); if (debug_ > 1) { Baa_.print("Alpha-alpha B(OBS+ABS+GBC1+GBC2) contribution"); Bab_.print("Alpha-beta B(OBS+ABS+GBC1+GBC2) contribution"); } } // Distribute the final intermediates to every node globally_sum_intermeds_(true); evaluated_ = true; } void R12IntEval::globally_sum_scmatrix_(RefSCMatrix& A, bool to_all_tasks, bool to_average) { Ref msg = r12info_->msg(); unsigned int ntasks = msg->n(); // If there's only one task then there's nothing to do if (ntasks == 1) return; const int nelem = A.ncol() * A.nrow(); double *A_array = new double[nelem]; A.convert(A_array); if (to_all_tasks) msg->sum(A_array,nelem,0,-1); else msg->sum(A_array,nelem,0,0); A.assign(A_array); if (to_average) A.scale(1.0/(double)ntasks); if (!to_all_tasks && msg->me() != 0) A.assign(0.0); delete[] A_array; } void R12IntEval::globally_sum_scvector_(RefSCVector& A, bool to_all_tasks, bool to_average) { Ref msg = r12info_->msg(); unsigned int ntasks = msg->n(); // If there's only one task then there's nothing to do if (ntasks == 1) return; const int nelem = A.dim().n(); double *A_array = new double[nelem]; A.convert(A_array); if (to_all_tasks) msg->sum(A_array,nelem,0,-1); else msg->sum(A_array,nelem,0,0); A.assign(A_array); if (to_average) A.scale(1.0/(double)ntasks); if (!to_all_tasks && msg->me() != 0) A.assign(0.0); delete[] A_array; } void R12IntEval::globally_sum_intermeds_(bool to_all_tasks) { globally_sum_scmatrix_(Vaa_,to_all_tasks); globally_sum_scmatrix_(Vab_,to_all_tasks); globally_sum_scmatrix_(Xaa_,to_all_tasks); globally_sum_scmatrix_(Xab_,to_all_tasks); globally_sum_scmatrix_(Baa_,to_all_tasks); globally_sum_scmatrix_(Bab_,to_all_tasks); if (ebc_ == false) { globally_sum_scmatrix_(Aaa_,to_all_tasks); globally_sum_scmatrix_(Aab_,to_all_tasks); if (follow_ks_ebcfree_) { globally_sum_scmatrix_(Ac_aa_,to_all_tasks); globally_sum_scmatrix_(Ac_ab_,to_all_tasks); } globally_sum_scmatrix_(T2aa_,to_all_tasks); globally_sum_scmatrix_(T2ab_,to_all_tasks); globally_sum_scmatrix_(Raa_,to_all_tasks); globally_sum_scmatrix_(Rab_,to_all_tasks); } globally_sum_scvector_(emp2pair_aa_,to_all_tasks); globally_sum_scvector_(emp2pair_ab_,to_all_tasks); if (debug_) { ExEnv::out0() << indent << "Collected contributions to the intermediates from all tasks"; if (to_all_tasks) ExEnv::out0() << " and distributed to every task" << endl; else ExEnv::out0() << " on task 0" << endl; } } ///////////////////////////////////////////////////////////////////////////// // Local Variables: // mode: c++ // c-file-style: "CLJ-CONDENSED" // End: