8 #ifndef CURVY_STEPS_HPP_
9 #define CURVY_STEPS_HPP_
12 #include "tiledarray_fock.hpp"
16 using Array2 = TA::Array<double,2>;
17 using Array3 = TA::Array<double,3>;
18 using Array4 = TA::Array<double,4>;
20 namespace curvy_steps {
23 Purify(Array2 &R,
const Array2 &S){
31 R(
"i,j") = (R(
"i,j") + R(
"j,i")) * 0.5;
37 const Array2 RS = R(
"i,k") * S(
"k,j");
40 const Array2 RSR = RS(
"i,k") * R(
"k,j");
41 const Array2 Rnew = 3 * RSR(
"i,j") - 2 * RS(
"i,m") * RSR(
"m,j");
42 const Array2 Rnorm_temp = Rnew(
"i,j") - R(
"i,j");
44 rdiff = TA::expressions::norminf(Rnorm_temp(
"i,j"));
46 }
while(rdiff > 1e-8);
50 Scom(
const Array2 &R,
const Array2 &X,
const Array2 &S){
53 Array2 RSX = R(
"i,k") * S(
"k,n") * X(
"n,j");
56 return RSX(
"i,j") + RSX(
"j,i");
60 RotateR(Array2 &R,
const Array2 &X,
const Array2 &S,
61 const size_t order = 4){
66 Array2 LHS = R(
"i,j");
69 double Fac[] = {1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800,
73 Array2 steps = Scom(R, X, S);
74 for(std::size_t i = 0; i < order; ++i){
78 LHS(
"i,j") = LHS(
"i,j") + 1/Fac[i] * steps(
"i,j");
79 steps = Scom(steps, X, S);
85 conjgradmat(
const Array2 &F, Array2 &X,
const Array2 &D,
86 const Array2 &Esymm,
const Array2 &S,
87 const Array2 &Eanti,
const std::size_t max_iter = 100) {
102 double Rnorm2 = TA::expressions::norm2(R(
"i,j"));
103 double Rsold = Rnorm2 * Rnorm2;
108 std::size_t count = 0;
110 F.world().gop.fence();
111 Array2 FPD = F(
"i,n") * P_i(
"n,m") * D(
"m,j");
112 Array2 SPEs = S(
"i,n") * P_i(
"n,m") * Esymm(
"m,j");
115 Array2 Ap_i = (FPD(
"i,j") - FPD(
"j,i") -
116 0.5 * (SPEs(
"i,j") - SPEs(
"j,i")) );
119 double alpha = Rsold / TA::expressions::dot(P_i(
"i,j"), Ap_i(
"i,j"));
122 Array2 d = alpha * P_i(
"i,j");
125 X(
"i,j") = X(
"i,j") + d(
"i,j");
128 R(
"i,j") = R(
"i,j") - alpha * Ap_i(
"i,j");
129 double Rsnew = TA::expressions::norm2(R(
"i,j"));
130 Rsnew = Rsnew * Rsnew;
133 P_i(
"i,j") = R(
"i,j") + (Rsnew/Rsold) * P_i(
"i,j");
137 }
while( std::sqrt(Rsold) >= 1e-5 && count < max_iter);
138 if(count == max_iter){
139 std::cout <<
"Convergence Factor in Conjgradmat = "
140 << std::sqrt(Rsold) << std::endl;
142 std::cout <<
"The maximum number of iterations was reached"
143 " in conjugate gradient" << std::endl;
145 F.world().gop.fence();
148 void Density_Update(Array2 &R,
const Array2 &S,
149 const Array2 &F,
const std::size_t iter,
150 const std::size_t rotation_order = 2){
161 Array2 FRS = F(
"i,n") * R(
"n,m") * S(
"m,j");
164 Array2 Eanti = FRS(
"i,j") - FRS(
"j,i");
166 Array2 Esymm = FRS(
"i,j") + FRS(
"j,i");
169 Array2 SRS = S(
"i,n") * R(
"n,m") * S(
"m,j");
173 Array2 XD(S.world(), S.trange());
174 XD.set_all_local(0.0);
177 conjgradmat(F, XD, SRS, Esymm, S, Eanti, iter * 20);
181 double scale = 0.1/TA::expressions::norminf(XD(
"i,j"));
182 XD(
"i,j") = XD(
"i,j") * std::min(1.0,scale);
184 XD.world().gop.fence();
186 RotateR(R,XD,S,rotation_order);
188 XD.world().gop.fence();
192 R.world().gop.fence();