1 //
2 // BAGEL - Brilliantly Advanced General Electronic Structure Library
3 // Filename: dkhcore.cc
4 // Copyright (C) 2016 Toru Shiozaki
5 //
6 // Author: Raymond Wang <raymondwang@u.northwestern.edu>
7 // Maintainer: Shiozaki group
8 //
9 // This file is part of the BAGEL package.
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //
24
25
26 #include <src/mat1e/dkhcore.h>
27 #include <src/mat1e/kinetic.h>
28 #include <src/mat1e/nai.h>
29 #include <src/mat1e/rel/small1e.h>
30 #include <src/mat1e/overlap.h>
31 #include <src/integral/os/overlapbatch.h>
32 #include <src/mat1e/mixedbasis.h>
33 #include <src/util/math/algo.h>
34
35 using namespace std;
36 using namespace bagel;
37
BOOST_CLASS_EXPORT_IMPLEMENT(DKHcore)38 BOOST_CLASS_EXPORT_IMPLEMENT(DKHcore)
39
40
41 DKHcore::DKHcore(shared_ptr<const Molecule> mol) : Matrix(mol->nbasis(), mol->nbasis()) {
42 init(mol);
43 }
44
45
init(shared_ptr<const Molecule> mol0)46 void DKHcore::init(shared_ptr<const Molecule> mol0) {
47
48 auto pre_scale = [](const VectorB& vec, const Matrix& mat) {
49 assert(mat.ndim() == vec.size());
50 shared_ptr<Matrix> out = mat.clone();
51 for (int i = 0; i != mat.mdim(); ++i)
52 for (int j = 0; j != mat.ndim(); ++j)
53 (*out)(j, i) = mat(j, i) * vec(j);
54 return out;
55 };
56
57 auto post_scale = [](const Matrix& mat, const VectorB& vec) {
58 assert(mat.mdim() == vec.size());
59 shared_ptr<Matrix> out = mat.copy();
60 for (int i = 0; i != mat.mdim(); ++i)
61 blas::scale_n(vec(i), out->element_ptr(0, i), mat.ndim());
62 return out;
63 };
64
65 auto mol = make_shared<Molecule>(*mol0);
66 mol = mol->uncontract();
67
68 // build DKH Hamiltonian in uncontracted basis
69 shared_ptr<const Matrix> transfer;
70 VectorB eig;
71 {
72 const Overlap overlap(mol);
73 shared_ptr<const Matrix> tildex = overlap.tildex();
74 const Kinetic kinetic(mol);
75 auto tmp = make_shared<Matrix>(*tildex % kinetic * *tildex);
76 eig = VectorB(tmp->ndim());
77 tmp->diagonalize(eig);
78 transfer = make_shared<Matrix>(*tildex * *tmp);
79 }
80
81 const double c2 = c__ * c__;
82 const int nunc = eig.size();
83 VectorB Ep(nunc);
84 VectorB A(nunc);
85 VectorB B(nunc);
86 VectorB RI(nunc);
87 VectorB RI_inv(nunc);
88 for (int i = 0; i != nunc; ++i) {
89 Ep(i) = c__ * std::sqrt(2.0 * eig(i) + c2);
90 A(i) = std::sqrt(0.5 * (Ep(i) + c2) / Ep(i));
91 B(i) = A(i) * c__ / (Ep(i) + c2);
92 RI(i) = 2.0 * eig(i) * pow((c__ / (Ep(i) + c2)), 2);
93 RI_inv(i) = 1.0 / RI(i);
94 }
95
96 const NAI nai(mol);
97 const Matrix V(*transfer % nai * *transfer);
98 const Small1e<NAIBatch> small1e(mol);
99 const Matrix smallnai(*transfer % small1e[0] * *transfer);
100
101 Matrix AVA(nunc, nunc);
102 Matrix BVB(nunc, nunc);
103 for (int i = 0; i != nunc; ++i)
104 for (int j = 0; j != nunc; ++j) {
105 const double denom = 1.0 / (Ep(j) + Ep(i));
106 AVA(j, i) = V(j, i) * A(j) * A(i) * denom ;
107 BVB(j, i) = smallnai(j, i) * B(j) * B(i) * denom;
108 }
109
110 Matrix dkh(nunc, nunc);
111 for (int i = 0; i != nunc; ++i)
112 dkh(i, i) = c2 * 2.0 * eig(i) / (Ep(i) + c2);
113
114 const Matrix EAVA(*pre_scale(Ep, AVA));
115 const Matrix AVARI(*post_scale(AVA, RI));
116 const Matrix AVAE(*post_scale(AVA, Ep));
117 const Matrix BVBE(*post_scale(BVB, Ep));
118 const Matrix EBVB(*pre_scale(Ep, BVB));
119
120 dkh += *post_scale(*pre_scale(A, V), A) + *post_scale(*pre_scale(B, smallnai), B) // Free Particle Projection
121 - BVB * (EAVA - 0.5 * (*pre_scale(RI_inv, BVBE)- AVAE))
122 - (AVAE + 0.5 * EAVA) * BVB + 0.5 * (*post_scale(EAVA, RI) - EBVB) * AVA
123 + 0.5 * EBVB * *pre_scale(RI_inv, BVB) + AVARI * (EAVA + 0.5 * AVAE)
124 + BVBE * *pre_scale(RI_inv, BVB) - 0.5 * AVA * BVBE; // DKH2
125
126 const MixedBasis<OverlapBatch> mix(mol0, mol);
127 const Matrix transfer2 = *transfer % mix;
128 Matrix_base<double>::operator=(transfer2 % dkh * transfer2);
129 }
130
131
132 /*
133 dkh += post_scale(pre_scale(A,V),A) + post_scale(pre_scale(B,smallnai),B)
134 - BVB * EAVA - AVAE * BVB + AVARI * EAVA
135 + BVBE * pre_scale(RI_inv,BVB) - 0.5 * BVB * AVAE - 0.5 * AVA * BVBE
136 + 0.5 * AVARI * AVAE + 0.5 * BVB * pre_scale(RI_inv,BVBE) - 0.5 * EBVB * AVA
137 - 0.5 * EAVA * BVB + 0.5 * EAVA * pre_scale(RI,AVA) + 0.5 * EBVB * pre_scale(RI_inv,BVB);
138 */
139
140 // Leave it here if we want do DKH2FULL in the future
141 /*
142 Matrix smallx(transfer % small1e[2] * transfer);
143 Matrix smally(transfer % small1e[3] * transfer);
144 Matrix smallz(transfer % small1e[1] * transfer);
145 for (int i = 0; i != ndim; ++i) {
146 for (int j = 0; j != ndim; ++j) {
147 const int denom = Ep(i) + Ep(j);
148 smallx(i,j) /= denom;
149 smally(i,j) /= denom;
150 smallz(i,j) /= denom;
151 }
152 }
153
154 const Matrix Xc(B * smallx * B);
155 const Matrix Yc(B * smally * B);
156 const Matrix Zc(B * smallz * B);
157
158 - Xc * Ep * RI_inv * Xc - Yc * Ep * RI_inv * Yc - Zc * Ep * RI_inv * Zc
159 - 0.5 * Xc * RI_inv * Xc * Ep - 0.5 * Yc * RI_inv * Yc * Ep - 0.5 * Zc * RI_inv * Zc * Ep
160 - 0.5 * Ep * Xc * RI_inv * Xc - 0.5 * Ep * Yc * RI_inv * Yc - 0.5 * Ep * Zc * RI_inv * Zc; // DKH2FULL
161 */
162