ABACUS develop
Atomic-orbital Based Ab-initio Computation at UStc
Loading...
Searching...
No Matches
pw_basis_big.h
Go to the documentation of this file.
1#ifndef PW_BASIS_BIG_H
2#define PW_BASIS_BIG_H
5
6#ifdef __MPI
7#include "mpi.h"
8#endif
9
10// temporary class, because previous ABACUS consider big grid for fft grids
11// which are used for grid integration in LCAO.
12// In fact, it is unnecessary. It will be moved after grid integration is refactored.
13namespace ModulePW
14{
15
17{
18public:
19 // combine [bx,by,bz] FFT grids into a big one
20 // typical values are bx=2, by=2, bz=2
21 // nbx=nx/bx, nby=ny/by, nbz=nz/bz,
23 {
24 }
25 PW_Basis_Big(std::string device_, std::string precision_) : PW_Basis_Sup(device_, precision_)
26 {
27 }
28
30 void setbxyz(const int bx_in, const int by_in, const int bz_in)
31 {
32 bx = bx_in;
33 by = by_in;
34 bz = bz_in;
35 bxyz = bx * by * bz;
36 }
37 int bx = 1, by = 1, bz = 1, bxyz = 1;
38 int nbx=0;
39 int nby=0;
40 int nbz=0;
41 int nbzp=0;
42 int nbxx=0;
44
45 void autoset_big_cell_size(int& b_size, const int& nc_size, const int nproc = 0)
46 {
47 //original default setting is 4
48 b_size = 4;
49 //only for bz
50 if(nproc > 0)
51 {
52 int candidate_lists[4] = {4, 3, 5, 2};
53 int max_bz[4];
54 for(int i=0;i<4;i++)
55 {
56 int tmp = candidate_lists[i];
57 max_bz[i] = nc_size / tmp;
58 if(nc_size % tmp!=0)
59 {//ignore candidates which can't be factored by nc_size
60 max_bz[i]=0;
61 continue;
62 }
63 if(max_bz[i] % nproc == 0)
64 {
65 b_size = tmp;
66 return;
67 }
68 }
69
70 //choose maximum residual
71 double res = 0.0;
72 double res_temp = 0.0;
73 for(int i=0;i<4;i++)
74 {
75 if(max_bz[i]==0) continue;
76 res_temp = double(max_bz[i] % nproc) / nproc;
77 if(res < res_temp)
78 {
79 res = res_temp;
80 b_size = candidate_lists[i];
81 }
82 }
83 return;
84 }
85 //for bx and by, choose maximum residual of (5,4,3)
86 else
87 {
88 int res = 0;
89 int res_temp = 0;
90 for(int i=5;i>2;i--)
91 {
92 res_temp = nc_size % i;
93 if(res_temp == 0)
94 {
95 b_size = i;
96 return;
97 }
98 else if(res < res_temp)
99 {
100 res = res_temp;
101 b_size = i;
102 }
103 }
104 return;
105 }
106 }
107
108
109 virtual void initgrids(const double lat0_in,const ModuleBase::Matrix3 latvec_in,
110 const double gridecut){
111 //init lattice
112 this->lat0 = lat0_in;
113 this->latvec = latvec_in;
114 this->omega = std::abs(latvec.Det()) * lat0 * lat0 * lat0;
115 this->GT = latvec.Inverse();
116 this->G = GT.Transpose();
117 this->GGT = G * GT;
118
119 //------------------------------------------------------------
120 //-------------------------init grids-------------------------
121 //------------------------------------------------------------
122 this->tpiba = ModuleBase::TWO_PI / this->lat0;
123 this->tpiba2 = this->tpiba * this->tpiba;
124 this->gridecut_lat = gridecut / tpiba2;
126 int *ibox = new int[3];
127
128 lat.x = latvec.e11;
129 lat.y = latvec.e12;
130 lat.z = latvec.e13;
131 ibox[0] = 2 * int(sqrt(gridecut_lat) * sqrt(lat * lat)) + 1;
132
133 lat.x = latvec.e21;
134 lat.y = latvec.e22;
135 lat.z = latvec.e23;
136 ibox[1] = 2 * int(sqrt(gridecut_lat) * sqrt(lat * lat)) + 1;
137
138 lat.x = latvec.e31;
139 lat.y = latvec.e32;
140 lat.z = latvec.e33;
141 ibox[2] = 2 * int(sqrt(gridecut_lat) * sqrt(lat * lat)) + 1;
142
143 // We should check if ibox is the minimum number to cover the planewave ball.
144 // Find the minimum number of ibox by traveling all possible ibox
145 int n1,n2,n3;
146 n1 = n2 = n3 = 0;
147 for(int igz = -ibox[2]+this->poolrank; igz <= ibox[2]; igz += this->poolnproc)
148 {
149 for(int igy = -ibox[1]; igy <= ibox[1]; ++igy)
150 {
151 for(int igx = -ibox[0]; igx <= ibox[0]; ++igx)
152 {
154 f.x = igx;
155 f.y = igy;
156 f.z = igz;
157 double modulus = f * (this->GGT * f);
158 if(modulus <= this->gridecut_lat)
159 {
160 if(n1 < std::abs(igx)) n1 = std::abs(igx);
161 if(n2 < std::abs(igy)) n2 = std::abs(igy);
162 if(n3 < std::abs(igz)) n3 = std::abs(igz);
163 }
164 }
165 }
166 }
167 ibox[0] = 2*n1+1;
168 ibox[1] = 2*n2+1;
169 ibox[2] = 2*n3+1;
170#ifdef __MPI
171 MPI_Allreduce(MPI_IN_PLACE, ibox, 3, MPI_INT, MPI_MAX , this->pool_world);
172#endif
173
174 // Find the minimal FFT box size the factors into the primes (2,3,5,7).
175 for (int i = 0; i < 3; i++)
176 {
177 int b = 0;
178 int n2 = 0;
179 int n3 = 0;
180 int n5 = 0;
181 //int n7 = 0;
182 bool done_factoring = false;
183
184 // increase ibox[i] by 1 until it is totally factorizable by (2,3,5,7)
185 do
186 {
187 b = ibox[i];
188
189 //n2 = n3 = n5 = n7 = 0;
190 n2 = n3 = n5 = 0;
191 done_factoring = false;
192 if ((this->full_pw && this->full_pw_dim == 2) && b % 2 != 0) done_factoring = true; // full_pw_dim = 2 means FFT dimensions should be even.
193 while (!done_factoring)
194 {
195 if (b % 2 == 0 && (!this->full_pw || this->full_pw_dim != 1)) // full_pw_dim = 1 means FFT dimension should be odd.
196 {
197 n2++;
198 b /= 2;
199 continue;
200 }
201 if (b % 3 == 0)
202 {
203 n3++;
204 b /= 3;
205 continue;
206 }
207 if (b % 5 == 0)
208 {
209 n5++;
210 b /= 5;
211 continue;
212 }
213 //if (b%7==0) { n7++; b /= 7; continue; }
214 done_factoring = true;
215 }
216 ibox[i] += 1;
217 }
218 while (b != 1);
219 ibox[i] -= 1;
220 // b==1 means fftbox[i] is (2,3,5,7) factorizable
221 }
222 //autoset bx/by/bz if not set in INPUT
223 if(!this->bz)
224 {
225 this->autoset_big_cell_size(this->bz, ibox[2], this->poolnproc);
226 }
227 if(!this->bx)
228 {
229 //if cz == cx, autoset bx==bz for keeping same symmetry
230 if(ibox[0] == ibox[2])
231 {
232 this->bx = this->bz;
233 }
234 else
235 {
236 this->autoset_big_cell_size(this->bx, ibox[0]);
237 }
238 }
239 if(!this->by)
240 {
241 //if cz == cy, autoset by==bz for keeping same symmetry
242 if(ibox[1] == ibox[2])
243 {
244 this->by = this->bz;
245 }
246 else
247 {
248 this->autoset_big_cell_size(this->by, ibox[1]);
249 }
250 }
251 this->bxyz = this->bx * this->by * this->bz;
252 if(ibox[0]%this->bx != 0) ibox[0] += (this->bx - ibox[0] % this->bx);
253 if(ibox[1]%this->by != 0) ibox[1] += (this->by - ibox[1] % this->by);
254 if(ibox[2]%this->bz != 0) ibox[2] += (this->bz - ibox[2] % this->bz);
255
256 this->nx = ibox[0];
257 this->ny = ibox[1];
258 this->nz = ibox[2];
259 this->nxy =this->nx * this->ny;
260 this->nxyz = this->nxy * this->nz;
261 this->nbx = this->nx / bx;
262 this->nby = this->ny / by;
263 this->nbz = this->nz / bz;
264
265 delete[] ibox;
266 return;
267
268 }
269
270 virtual void initgrids(
271 const double lat0_in,
272 const ModuleBase::Matrix3 latvec_in, // Unitcell lattice vectors
273 const int nx_in, int ny_in, int nz_in
274 )
275 {
276 this->lat0 = lat0_in;
277 this->tpiba = ModuleBase::TWO_PI / this->lat0;
278 this->tpiba2 = this->tpiba*this->tpiba;
279 this->latvec = latvec_in;
280 this->omega = std::abs(latvec.Det()) * lat0 * lat0 * lat0;
281 this->GT = latvec.Inverse();
282 this->G = GT.Transpose();
283 this->GGT = G * GT;
284 this->nx = nx_in;
285 this->ny = ny_in;
286 this->nz = nz_in;
287 // autoset bx/by/bz if not set in INPUT
288 if (!this->bz)
289 {
290 this->autoset_big_cell_size(this->bz, nz, this->poolnproc);
291 }
292 if (!this->bx)
293 {
294 // if cz == cx, autoset bx==bz for keeping same symmetry
295 if (nx == nz)
296 {
297 this->bx = this->bz;
298 }
299 else
300 {
301 this->autoset_big_cell_size(this->bx, nx);
302 }
303 }
304 if (!this->by)
305 {
306 // if cz == cy, autoset by==bz for keeping same symmetry
307 if (ny == nz)
308 {
309 this->by = this->bz;
310 }
311 else
312 {
313 this->autoset_big_cell_size(this->by, ny);
314 }
315 }
316 this->bxyz = this->bx * this->by * this->bz;
317 if(this->nx%this->bx != 0) this->nx += (this->bx - this->nx % this->bx);
318 if(this->ny%this->by != 0) this->ny += (this->by - this->ny % this->by);
319 if(this->nz%this->bz != 0) this->nz += (this->bz - this->nz % this->bz);
320 this->nbx = this->nx / bx;
321 this->nby = this->ny / by;
322 this->nbz = this->nz / bz;
323 this->nxy = this->nx * this->ny;
324 this->nxyz = this->nxy * this->nz;
325
326 int *ibox = new int[3];
327 ibox[0] = int((this->nx-1)/2)+1;
328 ibox[1] = int((this->ny-1)/2)+1;
329 ibox[2] = int((this->nz-1)/2)+1;
330 this->gridecut_lat = 1e20;
331 int count = 0;
332 for(int igz = -ibox[2]; igz <= ibox[2]; ++igz)
333 {
334 for(int igy = -ibox[1]; igy <= ibox[1]; ++igy)
335 {
336 for(int igx = -ibox[0]; igx <= ibox[0]; ++igx)
337 {
338 ++count;
339 if(count%this->poolnproc != this->poolrank) continue;
340 if(std::abs(igx)<=ibox[0]-1 && std::abs(igy)<=ibox[1]-1 && std::abs(igz)<=ibox[2]-1 ) continue;
342 f.x = igx;
343 f.y = igy;
344 f.z = igz;
345 double modulus = f * (this->GGT * f);
346 if(modulus < this->gridecut_lat)
347 {
348 this->gridecut_lat = modulus;
349 }
350 }
351 }
352 }
353#ifdef __MPI
354 MPI_Allreduce(MPI_IN_PLACE, &this->gridecut_lat, 1, MPI_DOUBLE, MPI_MIN , this->pool_world);
355#endif
356 this->gridecut_lat -= 1e-6;
357
358 delete[] ibox;
359
360 return;
361 }
362
363 virtual void distribute_r()
364 {
365 delete[] this->numz; this->numz = new int[this->poolnproc];
366 delete[] this->startz; this->startz = new int[this->poolnproc];
369
370 int npbz = this->nbz / this->poolnproc;
371 int modbz = this->nbz % this->poolnproc;
372 this->startz[0] = 0;
373 for(int ip = 0 ; ip < this->poolnproc ; ++ip)
374 {
375 this->numz[ip] = npbz*this->bz;
376 if(ip < modbz) this->numz[ip]+=this->bz;
377 if(ip < this->poolnproc - 1) this->startz[ip+1] = this->startz[ip] + numz[ip];
378 if(ip == this->poolrank)
379 {
380 this->nplane = numz[ip];
381 this->startz_current = startz[ip];
382 }
383 }
384 this->nbzp = this->nplane / this->bz;
385 this->nrxx = this->numz[this->poolrank] * this->nxy;
386 this->nbxx = this->nbzp * this->nbx * this->nby;
387 this->nbzp_start = this->startz[this->poolrank] / this->bz;
388 return;
389 }
390
391};
392}
393#endif
const std::complex< double > i
Definition cal_pLpR.cpp:46
3x3 matrix and related mathamatical operations
Definition matrix3.h:19
double e13
Definition matrix3.h:26
Matrix3 Inverse(void) const
Inverse a 3x3 matrix.
Definition matrix3.cpp:44
double e31
Definition matrix3.h:26
double e11
element e_ij: i_row, j_column
Definition matrix3.h:26
double e33
Definition matrix3.h:26
double e32
Definition matrix3.h:26
double e21
Definition matrix3.h:26
double e12
Definition matrix3.h:26
double Det(void) const
Calculate the determinant of a 3x3 matrix.
Definition matrix3.cpp:29
double e23
Definition matrix3.h:26
double e22
Definition matrix3.h:26
Matrix3 Transpose(void) const
Transpose a 3x3 matrix.
Definition matrix3.cpp:39
3 elements vector
Definition vector3.h:24
T x
Definition vector3.h:26
T y
Definition vector3.h:27
T z
Definition vector3.h:28
Definition pw_basis_big.h:17
void autoset_big_cell_size(int &b_size, const int &nc_size, const int nproc=0)
Definition pw_basis_big.h:45
int nbz
Definition pw_basis_big.h:40
int bx
Definition pw_basis_big.h:37
virtual void initgrids(const double lat0_in, const ModuleBase::Matrix3 latvec_in, const double gridecut)
Definition pw_basis_big.h:109
int nbx
Definition pw_basis_big.h:38
~PW_Basis_Big()
Definition pw_basis_big.h:29
virtual void distribute_r()
distribute real-space grids to different processors
Definition pw_basis_big.h:363
PW_Basis_Big()
Definition pw_basis_big.h:22
int nbzp_start
Definition pw_basis_big.h:43
PW_Basis_Big(std::string device_, std::string precision_)
Definition pw_basis_big.h:25
int by
Definition pw_basis_big.h:37
int nbxx
Definition pw_basis_big.h:42
int nby
Definition pw_basis_big.h:39
void setbxyz(const int bx_in, const int by_in, const int bz_in)
Definition pw_basis_big.h:30
int bz
Definition pw_basis_big.h:37
virtual void initgrids(const double lat0_in, const ModuleBase::Matrix3 latvec_in, const int nx_in, int ny_in, int nz_in)
Definition pw_basis_big.h:270
int bxyz
Definition pw_basis_big.h:37
int nbzp
Definition pw_basis_big.h:41
Special pw_basis class for sup girds, which is constrcuted in order to be consistent with the smooth ...
Definition pw_basis_sup.h:22
int nrxx
Definition pw_basis.h:120
double omega
volume of the cell
Definition pw_basis.h:178
int nx
Definition pw_basis.h:239
int * numz
Definition pw_basis.h:122
ModuleBase::Matrix3 GT
traspose of G
Definition pw_basis.h:176
int nxy
Definition pw_basis.h:239
double tpiba
2pi/lat0
Definition pw_basis.h:172
int poolnproc
Definition pw_basis.h:182
int ny
Definition pw_basis.h:239
int startz_current
Definition pw_basis.h:127
double lat0
unit length for lattice, unit in bohr
Definition pw_basis.h:171
int poolrank
Definition pw_basis.h:183
int nplane
Definition pw_basis.h:128
int full_pw_dim
Definition pw_basis.h:180
ModuleBase::Matrix3 latvec
Unitcell lattice vectors, unit in lat0.
Definition pw_basis.h:174
MPI_Comm pool_world
Definition pw_basis.h:103
ModuleBase::Matrix3 G
reciprocal lattice vector, unit in 1/lat0
Definition pw_basis.h:175
int nxyz
Definition pw_basis.h:239
bool full_pw
Definition pw_basis.h:167
double tpiba2
4pi^2/lat0^2
Definition pw_basis.h:173
int * startz
Definition pw_basis.h:121
ModuleBase::Matrix3 GGT
GGT = G*GT.
Definition pw_basis.h:177
double gridecut_lat
Energy cut off for all fft grids = ecutrho(Ry)*lat0^2/4pi^2, unit in 1/lat0^2.
Definition pw_basis.h:170
int nz
Definition pw_basis.h:239
void ZEROS(std::complex< T > *u, const TI n)
Definition global_function.h:109
const double TWO_PI
Definition constants.h:21
Definition pw_op.cpp:3