@@ -49,10 +49,6 @@ ElecStatePW<T, Device>::~ElecStatePW()
4949 delete[] this ->kin_r ;
5050 }
5151 }
52- if (PARAM .globalv .use_uspp )
53- {
54- delmem_var_h_op ()(this ->becsum );
55- }
5652 delmem_complex_op ()(this ->wfcr );
5753 delmem_complex_op ()(this ->wfcr_another_spin );
5854}
@@ -291,9 +287,8 @@ void ElecStatePW<T, Device>::cal_becsum(const psi::Psi<T, Device>& psi)
291287 const int nkb = this ->ppcell ->nkb ;
292288 this ->vkb = this ->ppcell ->template get_vkb_data <Real>();
293289 const int nh_tot = this ->ppcell ->nhm * (this ->ppcell ->nhm + 1 ) / 2 ;
294- // becsum on CPU (forces_us / stress_us use CPU dgemm)
295- resmem_var_h_op ()(becsum, nh_tot * ucell->nat * PARAM .inp .nspin , " ElecState<PW>::becsum" );
296- setmem_var_h_op ()(becsum, 0 , nh_tot * ucell->nat * PARAM .inp .nspin );
290+ const int becsum_size = nh_tot * ucell->nat * PARAM .inp .nspin ;
291+ this ->becsum_ .assign (becsum_size, 0.0 );
297292
298293 // becp: device buffer for gemm, then D2H for host loops
299294 T* becp = nullptr ;
@@ -429,11 +424,11 @@ void ElecStatePW<T, Device>::cal_becsum(const psi::Psi<T, Device>& psi)
429424 {
430425 if (ih == jh)
431426 {
432- becsum [index + ijh] += std::real (aux_gk_host[ih * nh_atom + jh]);
427+ this -> becsum_ [index + ijh] += static_cast < double >( std::real (aux_gk_host[ih * nh_atom + jh]) );
433428 }
434429 else
435430 {
436- becsum [index + ijh] += 2.0 * std::real (aux_gk_host[ih * nh_atom + jh]);
431+ this -> becsum_ [index + ijh] += 2.0 * static_cast < double >( std::real (aux_gk_host[ih * nh_atom + jh]) );
437432 }
438433 ijh++;
439434 }
@@ -470,7 +465,7 @@ void ElecStatePW<T, Device>::add_usrho(const psi::Psi<T, Device>& psi)
470465 // add to the charge density in reciprocal space the part which is due to the US augmentation.
471466 if (PARAM .globalv .use_uspp )
472467 {
473- this ->addusdens_g (becsum, this ->charge ->rhog );
468+ this ->addusdens_g (this ->charge ->rhog );
474469 }
475470 // transform back to real space using dense grids
476471 if (PARAM .globalv .double_grid || PARAM .globalv .use_uspp )
@@ -483,13 +478,14 @@ void ElecStatePW<T, Device>::add_usrho(const psi::Psi<T, Device>& psi)
483478}
484479
485480template <typename T, typename Device>
486- void ElecStatePW<T, Device>::addusdens_g(const Real* becsum, std::complex <double >** rhog)
481+ void ElecStatePW<T, Device>::addusdens_g(std::complex <double >** rhog)
487482{
488483 const T one{1 , 0 };
489484 const T zero{0 , 0 };
490485 const int npw = this ->charge ->rhopw ->npw ;
491486 const int lmaxq = this ->ppcell ->lmaxq ;
492487 const int nh_tot = this ->ppcell ->nhm * (this ->ppcell ->nhm + 1 ) / 2 ;
488+ const double * becsum = this ->becsum_ .data ();
493489 Structure_Factor* psf = this ->ppcell ->psf ;
494490 const std::complex <double > ci_tpi = ModuleBase::NEG_IMAG_UNIT * ModuleBase::TWO_PI ;
495491
@@ -577,11 +573,35 @@ void ElecStatePW<T, Device>::addusdens_g(const Real* becsum, std::complex<double
577573 delmem_var_op ()(ylmk0);
578574}
579575
576+ // Taoni add 2026-09-02
577+ // Added to fix USPP single force/stress reading the former float becsum as double.
578+ // The double-only drivers receive a base ElecState, while becsum belongs to the precision-templated ElecStatePW.
579+ // Refactor this bridge for true float force/stress.
580+ template <typename Device>
581+ const std::vector<double >* get_becsum (const ElecState& elec)
582+ {
583+ const ElecStatePW<std::complex <double >, Device>* double_elec = dynamic_cast <const ElecStatePW<std::complex <double >, Device>*>(&elec);
584+ if (double_elec != nullptr )
585+ {
586+ return &double_elec->get_becsum ();
587+ }
588+
589+ const ElecStatePW<std::complex <float >, Device>* single_elec = dynamic_cast <const ElecStatePW<std::complex <float >, Device>*>(&elec);
590+ if (single_elec != nullptr )
591+ {
592+ return &single_elec->get_becsum ();
593+ }
594+
595+ return nullptr ;
596+ }
597+
580598template class ElecStatePW <std::complex <float >, base_device::DEVICE_CPU >;
581599template class ElecStatePW <std::complex <double >, base_device::DEVICE_CPU >;
600+ template const std::vector<double >* get_becsum<base_device::DEVICE_CPU >(const ElecState& elec);
582601#if ((defined __CUDA) || (defined __ROCM))
583602template class ElecStatePW <std::complex <float >, base_device::DEVICE_GPU >;
584603template class ElecStatePW <std::complex <double >, base_device::DEVICE_GPU >;
604+ template const std::vector<double >* get_becsum<base_device::DEVICE_GPU >(const ElecState& elec);
585605#endif
586606
587607} // namespace elecstate
0 commit comments