@@ -37,21 +37,24 @@ void DiagoPPCG<T, Device>::orth_gradient(
3737 const T* psi, const T* spsi,
3838 std::vector<T>& grad) const
3939{
40+ std::vector<T> coeff (n_band_ * n_band_, T (0 ));
41+ gram (psi, grad.data (), n_band_, n_band_, coeff, n_band_);
42+
43+ #ifdef _OPENMP
44+ #pragma omp parallel for schedule(static) if (n_dim_ * n_band_ > 4096)
45+ #endif
4046 for (int j = 0 ; j < n_band_; ++j)
4147 {
4248 for (int i = 0 ; i < n_band_; ++i)
4349 {
44- // Full complex inner product <psi_i | grad_j>
45- const T* pi = psi + i * ld_psi_;
46- const T* gj = grad.data () + j * ld_psi_;
47- const T coeff = complex_dot (pi, gj);
48- if (std::abs (coeff) <= std::numeric_limits<Real>::epsilon ())
50+ const T cproj = coeff[i + j * n_band_];
51+ if (std::abs (cproj) <= std::numeric_limits<Real>::epsilon ())
4952 continue ;
5053 // grad_j -= S|psi_i> * coeff
5154 const T* si = spsi + i * ld_psi_;
5255 T* gj_out = grad.data () + j * ld_psi_;
5356 for (int ig = 0 ; ig < n_dim_; ++ig)
54- gj_out[ig] -= si[ig] * coeff ;
57+ gj_out[ig] -= si[ig] * cproj ;
5558 }
5659 }
5760}
@@ -163,6 +166,58 @@ void DiagoPPCG<T, Device>::line_minimize(
163166 const T* p, const T* hp, const T* sp,
164167 int ncol) const
165168{
169+ std::vector<double > h_ii_all (ncol, 0.0 );
170+ std::vector<double > s_ii_all (ncol, 0.0 );
171+ std::vector<double > h_pp_all (ncol, 0.0 );
172+ std::vector<double > s_pp_all (ncol, 0.0 );
173+ std::vector<T> h_ip_all (ncol, T (0 ));
174+ std::vector<T> s_ip_all (ncol, T (0 ));
175+
176+ #ifdef _OPENMP
177+ #pragma omp parallel for schedule(static) if (n_dim_ * ncol > 4096)
178+ #endif
179+ for (int j = 0 ; j < ncol; ++j)
180+ {
181+ const int off = j * ld_psi_;
182+ const T* pj = psi + off;
183+ const T* hj = hpsi + off;
184+ const T* sj = spsi + off;
185+ const T* pp = p + off;
186+ const T* hpp = hp + off;
187+ const T* spp = sp + off;
188+
189+ Real h_ii = 0 ;
190+ Real s_ii = 0 ;
191+ Real h_pp = 0 ;
192+ Real s_pp = 0 ;
193+ T h_ip = T (0 );
194+ T s_ip = T (0 );
195+
196+ for (int ig = 0 ; ig < n_dim_; ++ig)
197+ {
198+ h_ii += static_cast <Real>(std::real (std::conj (pj[ig]) * hj[ig]));
199+ s_ii += static_cast <Real>(std::real (std::conj (pj[ig]) * sj[ig]));
200+ h_ip += std::conj (pj[ig]) * hpp[ig];
201+ s_ip += std::conj (pj[ig]) * spp[ig];
202+ h_pp += static_cast <Real>(std::real (std::conj (pp[ig]) * hpp[ig]));
203+ s_pp += static_cast <Real>(std::real (std::conj (pp[ig]) * spp[ig]));
204+ }
205+
206+ h_ii_all[j] = static_cast <double >(h_ii);
207+ s_ii_all[j] = static_cast <double >(s_ii);
208+ h_ip_all[j] = h_ip;
209+ s_ip_all[j] = s_ip;
210+ h_pp_all[j] = static_cast <double >(h_pp);
211+ s_pp_all[j] = static_cast <double >(s_pp);
212+ }
213+
214+ reduce_pool_if_mpi_ready (h_ii_all.data (), ncol);
215+ reduce_pool_if_mpi_ready (s_ii_all.data (), ncol);
216+ reduce_pool_if_mpi_ready (h_ip_all.data (), ncol);
217+ reduce_pool_if_mpi_ready (s_ip_all.data (), ncol);
218+ reduce_pool_if_mpi_ready (h_pp_all.data (), ncol);
219+ reduce_pool_if_mpi_ready (s_pp_all.data (), ncol);
220+
166221 for (int j = 0 ; j < ncol; ++j)
167222 {
168223 const int off = j * ld_psi_;
@@ -173,12 +228,12 @@ void DiagoPPCG<T, Device>::line_minimize(
173228 const T* hpp = hp + off;
174229 const T* spp = sp + off;
175230
176- Real h_ii = gamma_dot (pj, hj );
177- Real s_ii = gamma_dot (pj, sj );
178- const T h_ip_c = complex_dot (pj, hpp) ;
179- const T s_ip_c = complex_dot (pj, spp) ;
180- Real h_pp = gamma_dot (pp, hpp );
181- Real s_pp = gamma_dot (pp, spp );
231+ Real h_ii = static_cast <Real>(h_ii_all[j] );
232+ Real s_ii = static_cast <Real>(s_ii_all[j] );
233+ const T h_ip_c = h_ip_all[j] ;
234+ const T s_ip_c = s_ip_all[j] ;
235+ Real h_pp = static_cast <Real>(h_pp_all[j] );
236+ Real s_pp = static_cast <Real>(s_pp_all[j] );
182237
183238 // Rotate the search direction so the first-order Rayleigh quotient
184239 // derivative is real. The scalar alpha solve below stays unchanged for
@@ -269,11 +324,8 @@ void DiagoPPCG<T, Device>::orth_cholesky(
269324 std::vector<T> spsi_orig (spsi, spsi + ld_psi_ * ncol);
270325
271326 // Gram matrix of S-orthonormality: J_{ij} = <psi_i | S | psi_j>
272- std::vector<T> gram_s (ncol * ncol, T (0 ));
273- for (int j = 0 ; j < ncol; ++j)
274- for (int i = 0 ; i < ncol; ++i)
275- gram_s[i + j * ncol] = complex_dot (psi + i * ld_psi_,
276- spsi + j * ld_psi_);
327+ std::vector<T> gram_s;
328+ gram (psi, spsi, ncol, ncol, gram_s, ncol);
277329
278330 bool cholesky_ok = false ;
279331 try
0 commit comments