11#include " source_base/global_function.h"
2- #include " source_base/global_variable.h"
32#include " source_io/module_parameter/parameter.h"
43#include " structure_factor.h"
54#include " source_base/constants.h"
87#include " source_base/timer.h"
98#include " source_base/libm/libm.h"
109
10+ #include < vector>
1111
1212#ifdef _OPENMP
1313#include < omp.h>
@@ -203,38 +203,38 @@ void Structure_Factor::setup(const UnitCell* Ucell, const Parallel_Grid& pgrid,
203203// norder: the order of Cardinal B-spline base functions
204204// FURTHER OPTIMIZATION:
205205// 1. Use "r2c" fft
206- // 2. Add parallel algorithm for fftw or na loop
207206//
208207void Structure_Factor::bspline_sf (const int norder,
209208 const UnitCell* Ucell,
210209 const Parallel_Grid& pgrid,
211210 const ModulePW::PW_Basis* rho_basis)
212211{
213- double *r = new double [rho_basis->nxyz ];
214- double *tmpr = new double [rho_basis->nrxx ];
215- double *zpiece = new double [rho_basis->nxy ];
216- std::complex <double > *b1 = new std::complex <double > [rho_basis->nx ];
217- std::complex <double > *b2 = new std::complex <double > [rho_basis->ny ];
218- std::complex <double > *b3 = new std::complex <double > [rho_basis->nz ];
212+ (void )pgrid;
213+ std::vector<double > tmpr (rho_basis->nrxx );
214+ std::vector<std::complex <double >> b1 (rho_basis->nx );
215+ std::vector<std::complex <double >> b2 (rho_basis->ny );
216+ std::vector<std::complex <double >> b3 (rho_basis->nz );
217+ const int nplane = rho_basis->nplane ;
218+ const int startz = rho_basis->startz_current ;
219219
220- for (int it=0 ; it<Ucell->ntype ; it++)
220+ // Each rank owns the same atoms; populate only its local FFT z slab.
221+ for (int it = 0 ; it < Ucell->ntype ; it++)
221222 {
222- const int na = Ucell->atoms [it].na ;
223- const ModuleBase::Vector3<double > * const taud = Ucell->atoms [it].taud .data ();
224- ModuleBase::GlobalFunc::ZEROS (r, rho_basis->nxyz );
223+ const int na = Ucell->atoms [it].na ;
224+ const ModuleBase::Vector3<double >* const taud = Ucell->atoms [it].taud .data ();
225+ ModuleBase::GlobalFunc::ZEROS (tmpr. data (), rho_basis->nrxx );
225226
226- // A parallel algorithm can be added in the future.
227227#ifdef _OPENMP
228- #pragma omp parallel for
228+ #pragma omp parallel for
229229#endif
230- for (int ia = 0 ; ia < na ; ++ia)
230+ for (int ia = 0 ; ia < na; ++ia)
231231 {
232- double gridx = taud[ia].x * rho_basis->nx ;
233- double gridy = taud[ia].y * rho_basis->ny ;
234- double gridz = taud[ia].z * rho_basis->nz ;
235- double dx = gridx - floor (gridx);
236- double dy = gridy - floor (gridy);
237- double dz = gridz - floor (gridz);
232+ const double gridx = taud[ia].x * rho_basis->nx ;
233+ const double gridy = taud[ia].y * rho_basis->ny ;
234+ const double gridz = taud[ia].z * rho_basis->nz ;
235+ const double dx = gridx - floor (gridx);
236+ const double dy = gridy - floor (gridy);
237+ const double dz = gridz - floor (gridz);
238238 // I'm not sure if there is a mod function for double data
239239
240240 ModuleBase::Bspline bsx, bsy, bsz;
@@ -245,79 +245,50 @@ void Structure_Factor::bspline_sf(const int norder,
245245 bsy.getbspline (dy);
246246 bsz.getbspline (dz);
247247
248- for (int iz = 0 ; iz <= norder ; ++iz)
248+ for (int iz = 0 ; iz <= norder; ++iz)
249249 {
250- int icz = int (rho_basis->nz * 10 -iz+ floor (gridz))% rho_basis->nz ;
251- for ( int iy = 0 ; iy <= norder ; ++iy )
250+ const int icz = int (rho_basis->nz * 10 - iz + floor (gridz)) % rho_basis->nz ;
251+ if (icz < startz || icz >= startz + nplane )
252252 {
253- int icy = int (rho_basis->ny *10 -iy+floor (gridy))%rho_basis->ny ;
254- for (int ix = 0 ; ix <= norder ; ++ix )
253+ continue ;
254+ }
255+ const int local_z = icz - startz;
256+ for (int iy = 0 ; iy <= norder; ++iy)
257+ {
258+ const int icy = int (rho_basis->ny * 10 - iy + floor (gridy)) % rho_basis->ny ;
259+ for (int ix = 0 ; ix <= norder; ++ix)
255260 {
256- int icx = int (rho_basis->nx * 10 -ix+ floor (gridx))% rho_basis->nx ;
261+ const int icx = int (rho_basis->nx * 10 - ix + floor (gridx)) % rho_basis->nx ;
257262#ifdef _OPENMP
258- #pragma omp atomic
263+ #pragma omp atomic
259264#endif
260- r[icz*rho_basis->ny *rho_basis->nx + icx*rho_basis->ny + icy] += bsz.bezier_ele (iz)
261- * bsy.bezier_ele (iy)
262- * bsx.bezier_ele (ix);
265+ tmpr[(icx * rho_basis->ny + icy) * nplane + local_z]
266+ += bsz.bezier_ele (iz) * bsy.bezier_ele (iy) * bsx.bezier_ele (ix);
263267 }
264268 }
265269 }
266270 }
267-
268- // distribute data to different processors for UFFT
269- // ---------------------------------------------------
270- for (int iz = 0 ; iz < rho_basis->nz ; iz++)
271- {
272- if (GlobalV::MY_RANK ==0 )
273- {
274- #ifdef _OPENMP
275- #pragma omp parallel for schedule(static, 512)
276- #endif
277- for (int ir = 0 ; ir < rho_basis->nxy ; ir++)
278- {
279- zpiece[ir] = r[iz*rho_basis->nxy + ir];
280- }
281- }
282-
283- #ifdef __MPI
284- pgrid.zpiece_to_all (zpiece, iz, tmpr);
285- #else
286- // Serial build: the whole real-space grid is local, so there is no
287- // pool to scatter to. zpiece_to_all() is MPI-only, which otherwise
288- // leaves tmpr uninitialized -> garbage structure factor and a wrong
289- // total energy. Fill tmpr directly, using the SAME real-space layout
290- // as zpiece_to_all's serial path: rho[ir*nczp + znow], i.e. xy index
291- // outer and z innermost (nczp == nz, znow == iz when serial).
292- for (int ir = 0 ; ir < rho_basis->nxy ; ir++)
293- {
294- tmpr[ir*rho_basis->nz + iz] = zpiece[ir];
295- }
296- #endif
297-
298- }
299- // ---------------------------------------------------
300271
301272 // It should be optimized with r2c
302- rho_basis->real2recip (tmpr, &strucFac (it,0 ));
303- this ->bsplinecoef (b1,b2,b3,rho_basis->nx , rho_basis->ny , rho_basis->nz , norder);
273+ rho_basis->real2recip (tmpr.data (), &strucFac (it, 0 ));
274+ this ->bsplinecoef (b1.data (),
275+ b2.data (),
276+ b3.data (),
277+ rho_basis->nx ,
278+ rho_basis->ny ,
279+ rho_basis->nz ,
280+ norder);
304281#ifdef _OPENMP
305- #pragma omp parallel for schedule(static, 128)
282+ #pragma omp parallel for schedule(static, 128)
306283#endif
307- for (int ig = 0 ; ig < rho_basis->npw ; ++ig)
284+ for (int ig = 0 ; ig < rho_basis->npw ; ++ig)
308285 {
309- int idx = int (rho_basis->gdirect [ig].x + 0.1 + rho_basis->nx )% rho_basis->nx ;
310- int idy = int (rho_basis->gdirect [ig].y + 0.1 + rho_basis->ny )% rho_basis->ny ;
311- int idz = int (rho_basis->gdirect [ig].z + 0.1 + rho_basis->nz )% rho_basis->nz ;
312- strucFac (it,ig) *= ( b1[idx] * b2[idy] * b3[idz] * double (rho_basis->nxyz ) );
286+ const int idx = int (rho_basis->gdirect [ig].x + 0.1 + rho_basis->nx ) % rho_basis->nx ;
287+ const int idy = int (rho_basis->gdirect [ig].y + 0.1 + rho_basis->ny ) % rho_basis->ny ;
288+ const int idz = int (rho_basis->gdirect [ig].z + 0.1 + rho_basis->nz ) % rho_basis->nz ;
289+ strucFac (it, ig) *= (b1[idx] * b2[idy] * b3[idz] * double (rho_basis->nxyz ));
313290 }
314- }
315- delete[] r;
316- delete[] tmpr;
317- delete[] zpiece;
318- delete[] b1;
319- delete[] b2;
320- delete[] b3;
291+ }
321292
322293 return ;
323294}
0 commit comments