@@ -35,51 +35,54 @@ void Get_pchg_lcao::begin_gamma(const UnitCell& ucell,
3535 assert (psi_gamma_ != nullptr );
3636 const int nrxx = pgrid.get_nrxx ();
3737 const int precision = 11 ;
38+ const std::vector<int > bands_picked = select_bands (out_pchg);
39+
40+ // LCAO output uses one global process pool after diagonalization.
41+ // Each spin component is accumulated independently on the distributed real-space grid.
3842 std::vector<std::vector<double >> rho (nspin_, std::vector<double >(nrxx));
3943 std::vector<double *> rho_pointers (nspin_);
4044 for (int is = 0 ; is < nspin_; ++is)
4145 {
4246 rho_pointers[is] = rho[is].data ();
4347 }
44- const std::vector<int > bands_picked = select_bands (out_pchg);
45-
4648 for (int ib = 0 ; ib < nbands_; ++ib)
4749 {
48- if (bands_picked[ib])
50+ if (! bands_picked[ib])
4951 {
50- ModuleBase::matrix state_weights (nspin_, nbands_);
51- const double spin_degeneracy = nspin_ == 1 ? 2.0 : 1.0 ;
52- for (int is = 0 ; is < nspin_; ++is)
53- {
54- state_weights (is, ib) = spin_degeneracy;
55- }
52+ continue ;
53+ }
5654
57- elecstate::DensityMatrix<double , double > DM (¶_orb_, nspin_);
58- elecstate::cal_dm_psi (¶_orb_, state_weights, *psi_gamma_, DM );
55+ // Build a complete one-particle state instead of reusing its SCF occupation.
56+ ModuleBase::matrix state_weights (nspin_, nbands_);
57+ const double spin_degeneracy = nspin_ == 1 ? 2.0 : 1.0 ;
58+ for (int is = 0 ; is < nspin_; ++is)
59+ {
60+ state_weights (is, ib) = spin_degeneracy;
61+ }
5962
60- for (int is = 0 ; is < nspin_; ++is)
61- {
62- std::fill (rho[is].begin (), rho[is].end (), 0.0 );
63- }
63+ // Construct a band-resolved density matrix before evaluating its density on the grid.
64+ elecstate::DensityMatrix<double , double > DM (¶_orb_, nspin_);
65+ elecstate::cal_dm_psi (¶_orb_, state_weights, *psi_gamma_, DM );
6466
65- DM .init_DMR (&grid_driver, &ucell);
66- DM .cal_DMR ();
67- ModuleGint::cal_gint_rho (DM .get_DMR_vector (), nspin_, rho_pointers.data ());
67+ for (int is = 0 ; is < nspin_; ++is)
68+ {
69+ std::fill (rho[is].begin (), rho[is].end (), 0.0 );
70+ }
6871
69- for (int is = 0 ; is < nspin_; ++is)
70- {
71- // ssc should be inside the inner loop to reset the string stream each time
72- std::stringstream ssc;
73- ssc << global_out_dir << " pchgi" << ib + 1 << " s" << is + 1 << " .cube" ;
72+ DM .init_DMR (&grid_driver, &ucell);
73+ DM .cal_DMR ();
74+ ModuleGint::cal_gint_rho (DM .get_DMR_vector (), nspin_, rho_pointers.data ());
7475
75- ofs_running << " Writing cube file " << ssc.str () << std::endl;
76+ for (int is = 0 ; is < nspin_; ++is)
77+ {
78+ std::stringstream ssc;
79+ ssc << global_out_dir << " pchgi" << ib + 1 << " s" << is + 1 << " .cube" ;
7680
77- ModuleIO::write_vdata_palgrid (pgrid, rho[is].data (), is, nspin_, 0 , ssc.str (), 0.0 , &ucell, precision, 0 , false , false );
78- }
81+ ofs_running << " Writing cube file " << ssc.str () << std::endl;
82+
83+ ModuleIO::write_vdata_palgrid (pgrid, rho[is].data (), is, nspin_, 0 , ssc.str (), 0.0 , &ucell, precision, 0 , false , false );
7984 }
8085 }
81-
82- return ;
8386}
8487
8588// For multi-k
@@ -103,13 +106,17 @@ void Get_pchg_lcao::begin_k(const ModulePW::PW_Basis& rho_pw,
103106 assert (pgrid.get_nrxx () == rho_pw.nrxx );
104107 const int nrxx = pgrid.get_nrxx ();
105108 const int precision = 11 ;
109+ const std::vector<int > bands_picked = select_bands (out_pchg);
110+
111+ // LCAO k-point parallelism is temporary; output uses the restored global layout.
106112 std::vector<std::vector<double >> rho (nspin_, std::vector<double >(nrxx));
107113 std::vector<double *> rho_pointers (nspin_);
108114 for (int is = 0 ; is < nspin_; ++is)
109115 {
110116 rho_pointers[is] = rho[is].data ();
111117 }
112118
119+ // A single-k density is not generally invariant under the full crystal symmetry group.
113120 const bool needs_symmetry = !if_separate_k && ModuleSymmetry::Symmetry::symm_flag == 1 ;
114121 std::vector<std::vector<std::complex <double >>> rhog;
115122 std::vector<std::complex <double >*> rhog_pointers;
@@ -122,106 +129,94 @@ void Get_pchg_lcao::begin_k(const ModulePW::PW_Basis& rho_pw,
122129 rhog_pointers[is] = rhog[is].data ();
123130 }
124131 }
125- const std::vector<int > bands_picked = select_bands (out_pchg);
126-
127132 for (int ib = 0 ; ib < nbands_; ++ib)
128133 {
129- if (bands_picked[ib])
134+ if (! bands_picked[ib])
130135 {
131- ModuleBase::matrix state_weights (kv.get_nks (), nbands_);
132- const double spin_degeneracy = nspin_ == 1 ? 2.0 : 1.0 ;
133- for (int ik = 0 ; ik < kv.get_nks (); ++ik)
134- {
135- state_weights (ik, ib) = if_separate_k ? spin_degeneracy : kv.wk [ik];
136- }
137-
138- const int nspin_dm = nspin_ == 2 ? 2 : 1 ;
139- const int nk_output = kv.get_nks () / nspin_dm;
140- elecstate::DensityMatrix<std::complex <double >, double > DM (¶_orb_, nspin_dm, kv.kvec_d , nk_output);
141- elecstate::cal_dm_psi (¶_orb_, state_weights, *psi_k_, DM );
136+ continue ;
137+ }
142138
143- // If contribution from different k-points need to be output separately
144- if (if_separate_k)
145- {
146- // For multi-k, loop over all real k-points
147- for (int ik = 0 ; ik < nk_output; ++ik)
148- {
149- for (int is = 0 ; is < nspin_; ++is)
150- {
151- std::fill (rho[is].begin (), rho[is].end (), 0.0 );
152- }
139+ // Separate-k output uses a full state, while merged output retains Brillouin-zone weights.
140+ ModuleBase::matrix state_weights (kv.get_nks (), nbands_);
141+ const double spin_degeneracy = nspin_ == 1 ? 2.0 : 1.0 ;
142+ for (int ik = 0 ; ik < kv.get_nks (); ++ik)
143+ {
144+ state_weights (ik, ib) = if_separate_k ? spin_degeneracy : kv.wk [ik];
145+ }
153146
154- DM .init_DMR (&grid_driver, &ucell);
155- DM .cal_DMR (ik);
156- ModuleGint::cal_gint_rho (DM .get_DMR_vector (), nspin_, rho_pointers.data ());
147+ // Collinear spin channels are stored as two k blocks; spinors use one block per k point.
148+ const int nspin_dm = nspin_ == 2 ? 2 : 1 ;
149+ const int nk_output = kv.get_nks () / nspin_dm;
150+ elecstate::DensityMatrix<std::complex <double >, double > DM (¶_orb_, nspin_dm, kv.kvec_d , nk_output);
151+ elecstate::cal_dm_psi (¶_orb_, state_weights, *psi_k_, DM );
157152
158- for (int is = 0 ; is < nspin_; ++is)
159- {
160- // ssc should be inside the inner loop to reset the string stream each time
161- std::stringstream ssc;
162- ssc << global_out_dir << " pchgi" << ib + 1 << " s" << is + 1 << " k" << ik + 1 << " .cube" ;
163-
164- ofs_running << " Writing cube file " << ssc.str () << std::endl;
165-
166- ModuleIO::write_vdata_palgrid (pgrid,
167- rho[is].data (),
168- is,
169- nspin_,
170- 0 ,
171- ssc.str (),
172- 0.0 ,
173- &ucell,
174- precision,
175- 0 ,
176- false ,
177- false );
178- }
179- }
180- }
181- else
153+ if (if_separate_k)
154+ {
155+ // Write each physical k point separately.
156+ for (int ik = 0 ; ik < nk_output; ++ik)
182157 {
183158 for (int is = 0 ; is < nspin_; ++is)
184159 {
185160 std::fill (rho[is].begin (), rho[is].end (), 0.0 );
186161 }
187162
188163 DM .init_DMR (&grid_driver, &ucell);
189- DM .cal_DMR ();
164+ // Transform only the requested real k point to avoid summing different k contributions.
165+ DM .cal_DMR (ik);
190166 ModuleGint::cal_gint_rho (DM .get_DMR_vector (), nspin_, rho_pointers.data ());
191167
192- // Symmetrize the charge density, otherwise the results are incorrect if the symmetry is on
193- if (needs_symmetry)
194- {
195- Symmetry_rho srho;
196- if (nspin_ == 4 )
197- {
198- srho.begin (0 , rho_pointers.data (), rhog_pointers.data (), rho_pw.npw , nullptr , &rho_pw, ucell.symm );
199- srho.begin_soc (rho_pointers.data (), rhog_pointers.data (), &rho_pw, ucell.symm );
200- }
201- else
202- {
203- for (int is = 0 ; is < nspin_; ++is)
204- {
205- srho.begin (is, rho_pointers.data (), rhog_pointers.data (), rho_pw.npw , nullptr , &rho_pw, ucell.symm );
206- }
207- }
208- }
209-
210168 for (int is = 0 ; is < nspin_; ++is)
211169 {
212- // ssc should be inside the inner loop to reset the string stream each time
213170 std::stringstream ssc;
214- ssc << global_out_dir << " pchgi" << ib + 1 << " s" << is + 1 << " .cube" ;
171+ ssc << global_out_dir << " pchgi" << ib + 1 << " s" << is + 1 << " k " << ik + 1 << " .cube" ;
215172
216173 ofs_running << " Writing cube file " << ssc.str () << std::endl;
217174
218175 ModuleIO::write_vdata_palgrid (pgrid, rho[is].data (), is, nspin_, 0 , ssc.str (), 0.0 , &ucell, precision, 0 , false , false );
219176 }
220177 }
221178 }
222- }
179+ else
180+ {
181+ for (int is = 0 ; is < nspin_; ++is)
182+ {
183+ std::fill (rho[is].begin (), rho[is].end (), 0.0 );
184+ }
223185
224- return ;
186+ DM .init_DMR (&grid_driver, &ucell);
187+ // The no-argument transform sums all local k-point contributions into one density.
188+ DM .cal_DMR ();
189+ ModuleGint::cal_gint_rho (DM .get_DMR_vector (), nspin_, rho_pointers.data ());
190+
191+ // Symmetrize only the merged density, using coupled spin rotations for nspin=4.
192+ if (needs_symmetry)
193+ {
194+ Symmetry_rho srho;
195+ if (nspin_ == 4 )
196+ {
197+ srho.begin (0 , rho_pointers.data (), rhog_pointers.data (), rho_pw.npw , nullptr , &rho_pw, ucell.symm );
198+ srho.begin_soc (rho_pointers.data (), rhog_pointers.data (), &rho_pw, ucell.symm );
199+ }
200+ else
201+ {
202+ for (int is = 0 ; is < nspin_; ++is)
203+ {
204+ srho.begin (is, rho_pointers.data (), rhog_pointers.data (), rho_pw.npw , nullptr , &rho_pw, ucell.symm );
205+ }
206+ }
207+ }
208+
209+ for (int is = 0 ; is < nspin_; ++is)
210+ {
211+ std::stringstream ssc;
212+ ssc << global_out_dir << " pchgi" << ib + 1 << " s" << is + 1 << " .cube" ;
213+
214+ ofs_running << " Writing cube file " << ssc.str () << std::endl;
215+
216+ ModuleIO::write_vdata_palgrid (pgrid, rho[is].data (), is, nspin_, 0 , ssc.str (), 0.0 , &ucell, precision, 0 , false , false );
217+ }
218+ }
219+ }
225220}
226221
227222std::vector<int > Get_pchg_lcao::select_bands (const std::vector<int >& out_pchg) const
0 commit comments