42
42
#include " psi4/libpsi4util/process.h"
43
43
#include " psi4/libiwl/iwl.hpp"
44
44
#include " psi4/libpsio/psio.hpp"
45
+ #include " psi4/lib3index/dfhelper.h"
45
46
46
47
#include " helpers/helpers.h"
47
48
#include " helpers/lbfgs/lbfgs.h"
@@ -59,9 +60,9 @@ using namespace ambit;
59
60
namespace forte {
60
61
61
62
MCSCF_ORB_GRAD::MCSCF_ORB_GRAD (std::shared_ptr<ForteOptions> options,
62
- std::shared_ptr<MOSpaceInfo> mo_space_info,
63
- std::shared_ptr<ForteIntegrals> ints, bool freeze_core )
64
- : options_(options), mo_space_info_(mo_space_info), ints_(ints), freeze_core_(freeze_core ) {
63
+ std::shared_ptr<MOSpaceInfo> mo_space_info,
64
+ std::shared_ptr<ForteIntegrals> ints, bool ignore_frozen )
65
+ : options_(options), mo_space_info_(mo_space_info), ints_(ints), ignore_frozen_(ignore_frozen ) {
65
66
startup ();
66
67
}
67
68
@@ -77,6 +78,33 @@ void MCSCF_ORB_GRAD::startup() {
77
78
78
79
// setup JK
79
80
JK_ = ints_->jk ();
81
+ if (ints_->integral_type () == IntegralType::DF or
82
+ ints_->integral_type () == IntegralType::DiskDF) {
83
+ tei_alg_ = options_->get_bool (" MCSCF_DF_TEIALG" ) ? TEIALG::DF : TEIALG::JK;
84
+
85
+ outfile->Printf (" \n\n DF-MCSCF adopts integrals from DFHelper of Psi4.\n " );
86
+
87
+ auto wfn = ints_->wfn ();
88
+ auto bs = wfn->basisset ();
89
+ auto bs_aux = wfn->get_basisset (" DF_BASIS_SCF" );
90
+
91
+ df_helper_ = std::make_shared<psi::DFHelper>(bs, bs_aux);
92
+ size_t mem_sys = psi::Process::environment.get_memory () / sizeof (double );
93
+ int64_t mem = mem_sys - JK_->memory_estimate ();
94
+ if (mem < 0 ) {
95
+ auto xb = to_xb (static_cast <size_t >(-mem), sizeof (double ));
96
+ std::string msg = " Not enough memory! Need at least " ;
97
+ msg += std::to_string (xb.first ) + " " + xb.second .c_str () + " more." ;
98
+ outfile->Printf (" \n %s" , msg.c_str ());
99
+ throw std::runtime_error (msg);
100
+ }
101
+ df_helper_->set_schwarz_cutoff (options_->get_double (" INTS_TOLERANCE" ));
102
+ df_helper_->set_fitting_condition (options_->get_double (" DF_FITTING_CONDITION" ));
103
+ df_helper_->set_memory (static_cast <size_t >(mem));
104
+ df_helper_->set_nthreads (omp_get_max_threads ());
105
+ df_helper_->set_print_lvl (0 );
106
+ df_helper_->initialize ();
107
+ }
80
108
81
109
// allocate memory for tensors and matrices
82
110
init_tensors ();
@@ -86,62 +114,49 @@ void MCSCF_ORB_GRAD::startup() {
86
114
}
87
115
88
116
void MCSCF_ORB_GRAD::setup_mos () {
117
+ label_to_mos_.clear ();
118
+ label_to_cmos_.clear ();
89
119
90
120
nirrep_ = mo_space_info_->nirrep ();
91
121
92
122
nsopi_ = ints_->nsopi ();
93
123
nmopi_ = mo_space_info_->dimension (" ALL" );
94
-
95
- if (freeze_core_) {
96
- ncmopi_ = mo_space_info_->dimension (" CORRELATED" );
97
- } else {
98
- ncmopi_ =
99
- mo_space_info_->dimension (" FROZEN_DOCC" ) + mo_space_info_->dimension (" CORRELATED" );
100
- }
101
-
102
124
ndoccpi_ = mo_space_info_->dimension (" INACTIVE_DOCC" );
103
- nfrzvpi_ = mo_space_info_->dimension (" FROZEN_UOCC" );
125
+ nactvpi_ = mo_space_info_->dimension (" ACTIVE" );
126
+ actv_mos_ = mo_space_info_->absolute_mo (" ACTIVE" );
104
127
105
- if (freeze_core_) {
106
- nfrzcpi_ = mo_space_info_->dimension (" FROZEN_DOCC" );
107
- core_mos_ = mo_space_info_->absolute_mo (" RESTRICTED_DOCC" );
108
- } else {
128
+ if (ignore_frozen_) {
129
+ ncmopi_ = mo_space_info_->dimension (" ALL" );
130
+ nfrzvpi_ = psi::Dimension (nirrep_);
109
131
nfrzcpi_ = psi::Dimension (nirrep_);
110
132
core_mos_ = mo_space_info_->absolute_mo (" INACTIVE_DOCC" );
133
+ label_to_mos_[" f" ] = std::vector<size_t >();
134
+ label_to_mos_[" u" ] = std::vector<size_t >();
135
+ label_to_mos_[" v" ] = mo_space_info_->absolute_mo (" INACTIVE_UOCC" );
136
+ label_to_cmos_[" c" ] = mo_space_info_->corr_absolute_mo (" INACTIVE_DOCC" );
137
+ label_to_cmos_[" v" ] = mo_space_info_->corr_absolute_mo (" INACTIVE_UOCC" );
138
+ } else {
139
+ ncmopi_ = mo_space_info_->dimension (" CORRELATED" );
140
+ nfrzvpi_ = mo_space_info_->dimension (" FROZEN_UOCC" );
141
+ nfrzcpi_ = mo_space_info_->dimension (" FROZEN_DOCC" );
142
+ core_mos_ = mo_space_info_->absolute_mo (" RESTRICTED_DOCC" );
143
+ label_to_mos_[" f" ] = mo_space_info_->absolute_mo (" FROZEN_DOCC" );
144
+ label_to_mos_[" u" ] = mo_space_info_->absolute_mo (" FROZEN_UOCC" );
145
+ label_to_mos_[" v" ] = mo_space_info_->absolute_mo (" RESTRICTED_UOCC" );
146
+ label_to_cmos_[" c" ] = mo_space_info_->corr_absolute_mo (" RESTRICTED_DOCC" );
147
+ label_to_cmos_[" v" ] = mo_space_info_->corr_absolute_mo (" RESTRICTED_UOCC" );
111
148
}
112
149
113
- nactvpi_ = mo_space_info_->dimension (" ACTIVE" );
114
- actv_mos_ = mo_space_info_->absolute_mo (" ACTIVE" );
150
+ label_to_mos_[" c" ] = core_mos_;
151
+ label_to_mos_[" a" ] = actv_mos_;
152
+ label_to_cmos_[" a" ] = mo_space_info_->corr_absolute_mo (" ACTIVE" );
115
153
116
154
nso_ = nsopi_.sum ();
117
155
nmo_ = nmopi_.sum ();
118
156
ncmo_ = ncmopi_.sum ();
119
157
nactv_ = nactvpi_.sum ();
120
158
nfrzc_ = nfrzcpi_.sum ();
121
159
122
- label_to_mos_.clear ();
123
-
124
- if (freeze_core_) {
125
- label_to_mos_[" f" ] = mo_space_info_->absolute_mo (" FROZEN_DOCC" );
126
- } else {
127
- label_to_mos_[" f" ] = std::vector<size_t >();
128
- }
129
- label_to_mos_[" c" ] = core_mos_;
130
- label_to_mos_[" a" ] = actv_mos_;
131
- label_to_mos_[" v" ] = mo_space_info_->absolute_mo (" RESTRICTED_UOCC" );
132
- label_to_mos_[" u" ] = mo_space_info_->absolute_mo (" FROZEN_UOCC" );
133
-
134
- label_to_cmos_.clear ();
135
- if (freeze_core_) {
136
- label_to_cmos_[" c" ] = mo_space_info_->corr_absolute_mo (" RESTRICTED_DOCC" );
137
- label_to_cmos_[" a" ] = mo_space_info_->corr_absolute_mo (" ACTIVE" );
138
- label_to_cmos_[" v" ] = mo_space_info_->corr_absolute_mo (" RESTRICTED_UOCC" );
139
- } else {
140
- label_to_cmos_[" c" ] = mo_space_info_->absolute_mo (" INACTIVE_DOCC" );
141
- label_to_cmos_[" a" ] = mo_space_info_->absolute_mo (" ACTIVE" );
142
- label_to_cmos_[" v" ] = mo_space_info_->absolute_mo (" RESTRICTED_UOCC" );
143
- }
144
-
145
160
// in Pitzer ordering
146
161
mos_rel_.resize (nmo_);
147
162
for (int h = 0 , offset = 0 ; h < nirrep_; ++h) {
@@ -456,7 +471,11 @@ void MCSCF_ORB_GRAD::build_mo_integrals() {
456
471
if (ints_->integral_type () == Custom) {
457
472
fill_tei_custom (V_);
458
473
} else {
459
- build_tei_from_ao ();
474
+ if (tei_alg_ == TEIALG::JK) {
475
+ build_tei_jk ();
476
+ } else {
477
+ build_tei_df ();
478
+ }
460
479
}
461
480
}
462
481
@@ -475,35 +494,68 @@ void MCSCF_ORB_GRAD::fill_tei_custom(ambit::BlockedTensor V) {
475
494
}
476
495
}
477
496
478
- void MCSCF_ORB_GRAD::build_tei_from_ao () {
497
+ void MCSCF_ORB_GRAD::build_tei_df () {
479
498
if (nactv_ == 0 )
480
499
return ;
481
500
482
- // This function will do an integral transformation using the JK builder,
483
- // and return the integrals of type <px|uy> = (pu|xy).
484
501
timer_on (" Build (pu|xy) integrals" );
485
502
486
- // Transform C matrix to C1 symmetry
487
- // JK does not support mixed symmetry needed for 4-index integrals (York 09/09/2020)
488
- auto aotoso = ints_->wfn ()->aotoso ();
489
- auto C_nosym = std::make_shared<psi::Matrix>(nso_, nmo_);
490
-
491
- // Transform from the SO to the AO basis for the C matrix
492
- // MO in Pitzer ordering and only keep the non-frozen MOs
493
- for (int h = 0 , index = 0 ; h < nirrep_; ++h) {
494
- for (int i = 0 ; i < nmopi_[h]; ++i) {
495
- int nao = nso_, nso_h = nsopi_[h];
503
+ auto C_nosym = ints_->Ca_SO2AO (C_);
496
504
497
- if (!nso_h)
498
- continue ;
505
+ auto Cact = std::make_shared<psi::Matrix>(" Cact" , nso_, nactv_);
506
+ for (size_t x = 0 ; x < nactv_; ++x) {
507
+ Cact->set_column (0 , x, C_nosym->get_column (0 , actv_mos_[x]));
508
+ }
499
509
500
- C_DGEMV (' N' , nao, nso_h, 1.0 , aotoso->pointer (h)[0 ], nso_h, &C_->pointer (h)[0 ][i],
501
- nmopi_[h], 0.0 , &C_nosym->pointer ()[0 ][index ], nmo_);
510
+ df_helper_->add_space (" ALL" , C_nosym);
511
+ df_helper_->add_space (" ACT" , Cact);
512
+ df_helper_->add_transformation (" B" , " ALL" , " ACT" , " Qpq" );
513
+ df_helper_->transform ();
514
+
515
+ auto B = df_helper_->get_tensor (" B" ); // naux * (nmo * nact)
516
+
517
+ size_t naux = df_helper_->get_naux ();
518
+ auto Baa = std::make_shared<psi::Matrix>(" Baa" , naux, nactv_ * nactv_);
519
+ for (size_t Q = 0 ; Q < naux; ++Q) {
520
+ for (size_t u = 0 , nua = 0 ; u < nactv_; ++u) {
521
+ nua = label_to_mos_[" a" ][u] * nactv_;
522
+ Baa->set (Q, u * nactv_ + u, B->get (Q, nua + u));
523
+ for (size_t v = u + 1 ; v < nactv_; ++v) {
524
+ Baa->set (Q, u * nactv_ + v, B->get (Q, nua + v));
525
+ Baa->set (Q, v * nactv_ + u, B->get (Q, nua + v));
526
+ }
527
+ }
528
+ }
502
529
503
- index += 1 ;
530
+ auto puxy = psi::linalg::doublet (B, Baa, true , false ); // (nmo * nactv) * (nactv * nactv)
531
+ auto puxy_ptr = puxy->get_pointer ();
532
+ for (const auto & [p_label, p_mos] : label_to_mos_) {
533
+ std::string block = p_label + " aaa" ;
534
+ auto & data = V_.block (block).data ();
535
+ for (size_t p = 0 , psize = p_mos.size (), nactv2 = nactv_ * nactv_; p < psize; ++p) {
536
+ for (size_t u = 0 ; u < nactv_; ++u) {
537
+ C_DCOPY (nactv2, puxy_ptr + (p_mos[p] * nactv_ + u) * nactv2, 1 ,
538
+ &data[(p * nactv_ + u) * nactv2], 1 );
539
+ }
504
540
}
505
541
}
506
542
543
+ df_helper_->clear_all ();
544
+ timer_off (" Build (pu|xy) integrals" );
545
+ }
546
+
547
+ void MCSCF_ORB_GRAD::build_tei_jk () {
548
+ if (nactv_ == 0 )
549
+ return ;
550
+
551
+ // This function will do an integral transformation using the JK builder,
552
+ // and return the integrals of type <px|uy> = (pu|xy).
553
+ timer_on (" Build (pu|xy) integrals" );
554
+
555
+ // Transform C matrix to C1 symmetry
556
+ // JK does not support mixed symmetry needed for 4-index integrals (York 09/09/2020)
557
+ auto C_nosym = ints_->Ca_SO2AO (C_);
558
+
507
559
// set up the active part of the C matrix
508
560
auto Cact = std::make_shared<psi::Matrix>(" Cact" , nso_, nactv_);
509
561
std::vector<std::shared_ptr<psi::Matrix>> Cact_vec (nactv_);
@@ -693,7 +745,7 @@ std::shared_ptr<psi::Matrix> MCSCF_ORB_GRAD::fock(std::shared_ptr<RDMs> rdms) {
693
745
}
694
746
695
747
double MCSCF_ORB_GRAD::evaluate (std::shared_ptr<psi::Vector> x, std::shared_ptr<psi::Vector> g,
696
- bool do_g) {
748
+ bool do_g) {
697
749
// if need to update orbitals and integrals
698
750
if (update_orbitals (x)) {
699
751
build_mo_integrals ();
@@ -812,7 +864,7 @@ std::shared_ptr<psi::Matrix> MCSCF_ORB_GRAD::cayley_trans(const std::shared_ptr<
812
864
813
865
std::vector<std::tuple<int , int , int >>
814
866
MCSCF_ORB_GRAD::test_orbital_rotations (const std::shared_ptr<psi::Matrix>& U,
815
- const std::string& warning_msg) {
867
+ const std::string& warning_msg) {
816
868
// the overlap between new and old orbitals is simply U
817
869
// O = Cold^T S Cnew = Cold^T S Cold U = U
818
870
// MOM projection index: Pj = sum_{i}^{actv} O_ij
@@ -900,7 +952,7 @@ void MCSCF_ORB_GRAD::compute_orbital_grad() {
900
952
}
901
953
902
954
void MCSCF_ORB_GRAD::hess_diag (std::shared_ptr<psi::Vector>,
903
- const std::shared_ptr<psi::Vector>& h0) {
955
+ const std::shared_ptr<psi::Vector>& h0) {
904
956
compute_orbital_hess_diag ();
905
957
h0->copy (*hess_diag_);
906
958
}
@@ -1006,7 +1058,7 @@ void MCSCF_ORB_GRAD::compute_orbital_hess_diag() {
1006
1058
}
1007
1059
1008
1060
void MCSCF_ORB_GRAD::reshape_rot_ambit (ambit::BlockedTensor bt,
1009
- const std::shared_ptr<psi::Vector>& sv) {
1061
+ const std::shared_ptr<psi::Vector>& sv) {
1010
1062
size_t vec_size = sv->dimpi ().sum ();
1011
1063
if (vec_size != nrot_) {
1012
1064
throw std::runtime_error (
0 commit comments