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