Skip to content

Commit de42d3a

Browse files
author
abacus_fixer
committed
refactor(dftu_pw): merge CPU/GPU branches into template, drop unused iter param
The CPU and GPU branches of cal_occ_pw (formerly L32-110 and L113-188) were near-verbatim duplicates, differing only in the device template parameter of OnsiteProjector and Psi. Merge them into a single template member function accumulate_occ_one_k<Device>, with explicit instantiation controlling CPU always compiled and GPU only under __CUDA/__ROCM. Also drop the iter parameter from cal_occ_pw signature since it was never used in the function body; update the call site in setup_dftu_pw.cpp accordingly. Files changed: - source/source_pw/module_pwdft/dftu_base.h - drop const int iter param from cal_occ_pw declaration - add template member declaration accumulate_occ_one_k<Device> - source/source_pw/module_pwdft/dftu_pw.cpp - drop iter param from cal_occ_pw implementation - replace ~80 lines of CPU/GPU duplicate code with two template calls - add accumulate_occ_one_k template definition and explicit instantiations at end of file - source/source_pw/module_pwdft/setup_dftu_pw.cpp - drop iter argument at call site Effects: - ~80 lines of duplicate code removed from dftu_pw.cpp - CPU/GPU inner loops (iat/ib/m1/m2 + nspin==4 Pauli block assembly) now maintained in a single template implementation - psi::Psi visibility confirmed transitively via onsite_proj.h Pending verification (build delegated to user): - make module_pwdft incremental build - DFT+U ctest (e.g. MODULE_DFTU label) - GPU build path (__CUDA/__ROCM) explicit instantiation
1 parent 42ff6f8 commit de42d3a

3 files changed

Lines changed: 105 additions & 156 deletions

File tree

source/source_pw/module_pwdft/dftu_base.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,9 @@ class Plus_U_Base
6161
void set_energy(const double &e) { energy_u = e; }
6262
void set_double_energy() { energy_u *= 2.0; }
6363

64-
/// interface for PW base
64+
/// interface for PW basis
6565
/// calculate the local occupation number matrix for PW based wave functions
66-
void cal_occ_pw(const int iter,
67-
const void* psi_in,
66+
void cal_occ_pw(const void* psi_in,
6867
const ModuleBase::matrix& wg_in,
6968
const UnitCell& cell,
7069
Charge_Mixing* p_chgmix,
@@ -178,6 +177,13 @@ class Plus_U_Base
178177
void mix_occ_mat(const UnitCell& ucell, const double& mixing_beta);
179178
void set_occ_mat(const UnitCell& ucell);
180179

180+
/// accumulate occ_mat from psi for all k-points (per-device template)
181+
template <typename Device>
182+
void accumulate_occ_one_k(const void* psi_in,
183+
const ModuleBase::matrix& wg_in,
184+
const UnitCell& cell,
185+
const int* isk);
186+
181187
std::vector<std::complex<double>> eff_pot_pw;
182188
std::vector<int> eff_pot_pw_index;
183189
std::vector<double> uom_array;

source/source_pw/module_pwdft/dftu_pw.cpp

Lines changed: 95 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
/// nspin=4 (npol=2): spinor calculation;
1919
/// occ_mat has a single matrix of size (2*tlp1) x (2*tlp1) per atom
2020
/// storing all 4 Pauli blocks contiguously.
21-
void Plus_U_Base::cal_occ_pw(const int iter,
22-
const void* psi_in,
21+
void Plus_U_Base::cal_occ_pw(const void* psi_in,
2322
const ModuleBase::matrix& wg_in,
2423
const UnitCell& cell,
2524
Charge_Mixing* p_chgmix,
@@ -31,160 +30,12 @@ void Plus_U_Base::cal_occ_pw(const int iter,
3130

3231
if(this->device == "cpu")
3332
{
34-
auto* onsite_p = projectors::OnsiteProjector<double, base_device::DEVICE_CPU>::get_instance();
35-
const psi::Psi<std::complex<double>>* psi_p = (const psi::Psi<std::complex<double>>*)psi_in;
36-
const int nbands = psi_p->get_nbands();
37-
const int npol = psi_p->get_npol();
38-
for(int ik = 0; ik < psi_p->get_nk(); ik++)
39-
{
40-
int is = (this->nspin == 2) ? isk[ik] : 0;
41-
psi_p->fix_k(ik);
42-
onsite_p->tabulate_atomic(ik);
43-
44-
onsite_p->overlap_proj_psi(nbands*npol, psi_p->get_pointer());
45-
const std::complex<double>* becp = onsite_p->get_h_becp();
46-
int nkb = onsite_p->get_size_becp() / nbands / npol;
47-
48-
int begin_ih = 0;
49-
for(int iat = 0; iat < cell.nat; iat++)
50-
{
51-
const int it = cell.iat2it[iat];
52-
const int nh = onsite_p->get_nh(iat);
53-
const int target_l = get_orbital_corr(it);
54-
if(!has_correlated_orbital(it))
55-
{
56-
begin_ih += nh;
57-
continue;
58-
}
59-
const int m_begin = target_l * target_l;
60-
const int tlp1 = 2 * target_l + 1;
61-
const int tlp1_2 = tlp1 * tlp1;
62-
if(this->nspin == 4)
63-
{
64-
for(int ib = 0;ib<nbands;ib++)
65-
{
66-
const double weight = wg_in(ik, ib);
67-
int ind_m1m2 = 0;
68-
for(int m1 = 0; m1 < tlp1; m1++)
69-
{
70-
const int index_m1 = ib*npol*nkb + begin_ih + m_begin + m1;
71-
for(int m2 = 0; m2 < tlp1; m2++)
72-
{
73-
const int index_m2 = ib*npol*nkb + begin_ih + m_begin + m2;
74-
std::complex<double> occ[4];
75-
occ[0] = weight * conj(becp[index_m1]) * becp[index_m2];
76-
occ[1] = weight * conj(becp[index_m1]) * becp[index_m2 + nkb];
77-
occ[2] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2];
78-
occ[3] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2 + nkb];
79-
this->occ_mat[iat][target_l][0][0].c[ind_m1m2] += (occ[0] + occ[3]).real();
80-
this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + tlp1_2] += (occ[1] + occ[2]).real();
81-
this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 2 * tlp1_2] += (occ[1] - occ[2]).imag();
82-
this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 3 * tlp1_2] += (occ[0] - occ[3]).real();
83-
ind_m1m2++;
84-
}
85-
}
86-
}// ib
87-
}
88-
else // nspin=1 or nspin=2
89-
{
90-
for(int ib = 0;ib<nbands;ib++)
91-
{
92-
const double weight = wg_in(ik, ib);
93-
int ind_m1m2 = 0;
94-
for(int m1 = 0; m1 < tlp1; m1++)
95-
{
96-
const int index_m1 = ib*nkb + begin_ih + m_begin + m1;
97-
for(int m2 = 0; m2 < tlp1; m2++)
98-
{
99-
const int index_m2 = ib*nkb + begin_ih + m_begin + m2;
100-
this->occ_mat[iat][target_l][0][is].c[ind_m1m2] += weight * (conj(becp[index_m1]) * becp[index_m2]).real();
101-
ind_m1m2++;
102-
}
103-
}
104-
}// ib
105-
}
106-
begin_ih += nh;
107-
}// iat
108-
109-
}// ik
33+
this->accumulate_occ_one_k<base_device::DEVICE_CPU>(psi_in, wg_in, cell, isk);
11034
}
11135
#if defined(__CUDA) || defined(__ROCM)
11236
else
11337
{
114-
auto* onsite_p = projectors::OnsiteProjector<double, base_device::DEVICE_GPU>::get_instance();
115-
const psi::Psi<std::complex<double>, base_device::DEVICE_GPU>* psi_p = (const psi::Psi<std::complex<double>, base_device::DEVICE_GPU>*)psi_in;
116-
const int nbands = psi_p->get_nbands();
117-
const int npol = psi_p->get_npol();
118-
for(int ik = 0; ik < psi_p->get_nk(); ik++)
119-
{
120-
int is = (this->nspin == 2) ? isk[ik] : 0;
121-
psi_p->fix_k(ik);
122-
onsite_p->tabulate_atomic(ik);
123-
124-
onsite_p->overlap_proj_psi(nbands*npol, psi_p->get_pointer());
125-
const std::complex<double>* becp = onsite_p->get_h_becp();
126-
int nkb = onsite_p->get_size_becp() / nbands / npol;
127-
int begin_ih = 0;
128-
for(int iat = 0; iat < cell.nat; iat++)
129-
{
130-
const int it = cell.iat2it[iat];
131-
const int nh = onsite_p->get_nh(iat);
132-
const int target_l = get_orbital_corr(it);
133-
if(!has_correlated_orbital(it))
134-
{
135-
begin_ih += nh;
136-
continue;
137-
}
138-
const int m_begin = target_l * target_l;
139-
const int tlp1 = 2 * target_l + 1;
140-
const int tlp1_2 = tlp1 * tlp1;
141-
if(this->nspin == 4)
142-
{
143-
for(int ib = 0;ib<nbands;ib++)
144-
{
145-
const double weight = wg_in(ik, ib);
146-
int ind_m1m2 = 0;
147-
for(int m1 = 0; m1 < tlp1; m1++)
148-
{
149-
const int index_m1 = ib*npol*nkb + begin_ih + m_begin + m1;
150-
for(int m2 = 0; m2 < tlp1; m2++)
151-
{
152-
const int index_m2 = ib*npol*nkb + begin_ih + m_begin + m2;
153-
std::complex<double> occ[4];
154-
occ[0] = weight * conj(becp[index_m1]) * becp[index_m2];
155-
occ[1] = weight * conj(becp[index_m1]) * becp[index_m2 + nkb];
156-
occ[2] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2];
157-
occ[3] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2 + nkb];
158-
this->occ_mat[iat][target_l][0][0].c[ind_m1m2] += (occ[0] + occ[3]).real();
159-
this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + tlp1_2] += (occ[1] + occ[2]).real();
160-
this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 2 * tlp1_2] += (occ[1] - occ[2]).imag();
161-
this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 3 * tlp1_2] += (occ[0] - occ[3]).real();
162-
ind_m1m2++;
163-
}
164-
}
165-
}// ib
166-
}
167-
else // nspin=1 or nspin=2
168-
{
169-
for(int ib = 0;ib<nbands;ib++)
170-
{
171-
const double weight = wg_in(ik, ib);
172-
int ind_m1m2 = 0;
173-
for(int m1 = 0; m1 < tlp1; m1++)
174-
{
175-
const int index_m1 = ib*nkb + begin_ih + m_begin + m1;
176-
for(int m2 = 0; m2 < tlp1; m2++)
177-
{
178-
const int index_m2 = ib*nkb + begin_ih + m_begin + m2;
179-
this->occ_mat[iat][target_l][0][is].c[ind_m1m2] += weight * (conj(becp[index_m1]) * becp[index_m2]).real();
180-
ind_m1m2++;
181-
}
182-
}
183-
}// ib
184-
}
185-
begin_ih += nh;
186-
}// iat
187-
}// ik
38+
this->accumulate_occ_one_k<base_device::DEVICE_GPU>(psi_in, wg_in, cell, isk);
18839
}
18940
#endif
19041

@@ -347,3 +198,95 @@ void Plus_U_Base::cal_occ_pw(const int iter,
347198

348199
ModuleBase::timer::end("Plus_U_Base", "cal_occ_pw");
349200
}
201+
202+
template <typename Device>
203+
void Plus_U_Base::accumulate_occ_one_k(const void* psi_in,
204+
const ModuleBase::matrix& wg_in,
205+
const UnitCell& cell,
206+
const int* isk)
207+
{
208+
auto* onsite_p = projectors::OnsiteProjector<double, Device>::get_instance();
209+
const psi::Psi<std::complex<double>, Device>* psi_p =
210+
(const psi::Psi<std::complex<double>, Device>*)psi_in;
211+
const int nbands = psi_p->get_nbands();
212+
const int npol = psi_p->get_npol();
213+
for(int ik = 0; ik < psi_p->get_nk(); ik++)
214+
{
215+
int is = (this->nspin == 2) ? isk[ik] : 0;
216+
psi_p->fix_k(ik);
217+
onsite_p->tabulate_atomic(ik);
218+
219+
onsite_p->overlap_proj_psi(nbands*npol, psi_p->get_pointer());
220+
const std::complex<double>* becp = onsite_p->get_h_becp();
221+
int nkb = onsite_p->get_size_becp() / nbands / npol;
222+
223+
int begin_ih = 0;
224+
for(int iat = 0; iat < cell.nat; iat++)
225+
{
226+
const int it = cell.iat2it[iat];
227+
const int nh = onsite_p->get_nh(iat);
228+
const int target_l = get_orbital_corr(it);
229+
if(!has_correlated_orbital(it))
230+
{
231+
begin_ih += nh;
232+
continue;
233+
}
234+
const int m_begin = target_l * target_l;
235+
const int tlp1 = 2 * target_l + 1;
236+
const int tlp1_2 = tlp1 * tlp1;
237+
if(this->nspin == 4)
238+
{
239+
for(int ib = 0; ib < nbands; ib++)
240+
{
241+
const double weight = wg_in(ik, ib);
242+
int ind_m1m2 = 0;
243+
for(int m1 = 0; m1 < tlp1; m1++)
244+
{
245+
const int index_m1 = ib*npol*nkb + begin_ih + m_begin + m1;
246+
for(int m2 = 0; m2 < tlp1; m2++)
247+
{
248+
const int index_m2 = ib*npol*nkb + begin_ih + m_begin + m2;
249+
std::complex<double> occ[4];
250+
occ[0] = weight * conj(becp[index_m1]) * becp[index_m2];
251+
occ[1] = weight * conj(becp[index_m1]) * becp[index_m2 + nkb];
252+
occ[2] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2];
253+
occ[3] = weight * conj(becp[index_m1 + nkb]) * becp[index_m2 + nkb];
254+
this->occ_mat[iat][target_l][0][0].c[ind_m1m2] += (occ[0] + occ[3]).real();
255+
this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + tlp1_2] += (occ[1] + occ[2]).real();
256+
this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 2 * tlp1_2] += (occ[1] - occ[2]).imag();
257+
this->occ_mat[iat][target_l][0][0].c[ind_m1m2 + 3 * tlp1_2] += (occ[0] - occ[3]).real();
258+
ind_m1m2++;
259+
}
260+
}
261+
}
262+
}
263+
else // nspin=1 or nspin=2
264+
{
265+
for(int ib = 0; ib < nbands; ib++)
266+
{
267+
const double weight = wg_in(ik, ib);
268+
int ind_m1m2 = 0;
269+
for(int m1 = 0; m1 < tlp1; m1++)
270+
{
271+
const int index_m1 = ib*nkb + begin_ih + m_begin + m1;
272+
for(int m2 = 0; m2 < tlp1; m2++)
273+
{
274+
const int index_m2 = ib*nkb + begin_ih + m_begin + m2;
275+
this->occ_mat[iat][target_l][0][is].c[ind_m1m2] += weight * (conj(becp[index_m1]) * becp[index_m2]).real();
276+
ind_m1m2++;
277+
}
278+
}
279+
}
280+
}
281+
begin_ih += nh;
282+
}
283+
}
284+
}
285+
286+
// explicit instantiations
287+
template void Plus_U_Base::accumulate_occ_one_k<base_device::DEVICE_CPU>(
288+
const void*, const ModuleBase::matrix&, const UnitCell&, const int*);
289+
#if defined(__CUDA) || defined(__ROCM)
290+
template void Plus_U_Base::accumulate_occ_one_k<base_device::DEVICE_GPU>(
291+
const void*, const ModuleBase::matrix&, const UnitCell&, const int*);
292+
#endif

source/source_pw/module_pwdft/setup_dftu_pw.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ void iter_init_dftu_pw(const int iter,
2727

2828
if (dftu.get_occ_mat_ctrl() != 2)
2929
{
30-
dftu.cal_occ_pw(iter, psi, wg, ucell, p_chgmix, isk);
30+
dftu.cal_occ_pw(psi, wg, ucell, p_chgmix, isk);
3131
}
3232
dftu_io::output(dftu, ucell, PARAM.inp.out_chg[0], PARAM.globalv.global_out_dir, PARAM.inp.nspin, PARAM.globalv.npol);
3333
}

0 commit comments

Comments
 (0)