Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Performs a wavelet based solution of the Poisson equation.
10 : !> \author Florian Schiffmann (09.2007,fschiff)
11 : ! **************************************************************************************************
12 : MODULE ps_wavelet_util
13 :
14 : USE kinds, ONLY: dp
15 : USE mathconstants, ONLY: fourpi
16 : USE ps_wavelet_base, ONLY: f_poissonsolver,&
17 : p_poissonsolver,&
18 : s_poissonsolver
19 : USE ps_wavelet_fft3d, ONLY: fourier_dim
20 : USE pw_grid_types, ONLY: pw_grid_type
21 : #include "../base/base_uses.f90"
22 :
23 : IMPLICIT NONE
24 :
25 : PRIVATE
26 :
27 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ps_wavelet_util'
28 :
29 : ! *** Public data types ***
30 :
31 : PUBLIC :: PSolver, &
32 : P_FFT_dimensions, &
33 : S_FFT_dimensions, &
34 : F_FFT_dimensions
35 :
36 : CONTAINS
37 :
38 : ! **************************************************************************************************
39 : !> \brief Calculate the Poisson equation $\nabla^2 V(x,y,z)=-4 \pi \rho(x,y,z)$
40 : !> from a given $\rho$, for different boundary conditions an for different data distributions.
41 : !> Following the boundary conditions, it applies the Poisson Kernel previously calculated.
42 : !> \param geocode Indicates the boundary conditions (BC) of the problem:
43 : !> 'F' free BC, isolated systems.
44 : !> The program calculates the solution as if the given density is
45 : !> "alone" in R^3 space.
46 : !> 'S' surface BC, isolated in y direction, periodic in xz plane
47 : !> The given density is supposed to be periodic in the xz plane,
48 : !> so the dimensions in these direction mus be compatible with the FFT
49 : !> Beware of the fact that the isolated direction is y!
50 : !> 'P' periodic BC.
51 : !> The density is supposed to be periodic in all the three directions,
52 : !> then all the dimensions must be compatible with the FFT.
53 : !> No need for setting up the kernel.
54 : !> \param iproc label of the process,from 0 to nproc-1
55 : !> \param nproc number of processors
56 : !> \param n01 global dimension in the three directions.
57 : !> \param n02 global dimension in the three directions.
58 : !> \param n03 global dimension in the three directions.
59 : !> \param hx grid spacings. For the isolated BC case for the moment they are supposed to
60 : !> be equal in the three directions
61 : !> \param hy grid spacings. For the isolated BC case for the moment they are supposed to
62 : !> be equal in the three directions
63 : !> \param hz grid spacings. For the isolated BC case for the moment they are supposed to
64 : !> be equal in the three directions
65 : !> \param rhopot main input/output array.
66 : !> On input, it represents the density values on the grid points
67 : !> On output, it is the Hartree potential, namely the solution of the Poisson
68 : !> equation PLUS (when ixc/=0) the XC potential PLUS (again for ixc/=0) the
69 : !> pot_ion array. The output is non overlapping, in the sense that it does not
70 : !> consider the points that are related to gradient and WB calculation
71 : !> \param karray kernel of the poisson equation. It is provided in distributed case, with
72 : !> dimensions that are related to the output of the PS_dim4allocation routine
73 : !> it MUST be created by following the same geocode as the Poisson Solver.
74 : !> \param pw_grid ...
75 : !> \date February 2007
76 : !> \author Luigi Genovese
77 : !> \note The dimensions of the arrays must be compatible with geocode, nproc,
78 : !> ixc and iproc. Since the arguments of these routines are indicated with the *, it
79 : !> is IMPERATIVE to use the PS_dim4allocation routine for calculation arrays sizes.
80 : ! **************************************************************************************************
81 31829 : SUBROUTINE PSolver(geocode, iproc, nproc, n01, n02, n03, hx, hy, hz, &
82 : rhopot, karray, pw_grid)
83 : CHARACTER(len=1), INTENT(in) :: geocode
84 : INTEGER, INTENT(in) :: iproc, nproc, n01, n02, n03
85 : REAL(KIND=dp), INTENT(in) :: hx, hy, hz
86 : REAL(KIND=dp), DIMENSION(*), INTENT(inout) :: rhopot
87 : REAL(KIND=dp), DIMENSION(*), INTENT(in) :: karray
88 : TYPE(pw_grid_type), POINTER :: pw_grid
89 :
90 : INTEGER :: i1, i2, i3, iend, istart, j2, m1, m2, &
91 : m3, md1, md2, md3, n1, n2, n3, nd1, &
92 : nd2, nd3, nlim, nwb, nwbl, nwbr, nxc, &
93 : nxcl, nxcr, nxt
94 : REAL(KIND=dp) :: factor, hgrid, red_fact, scal
95 31829 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: zf
96 :
97 : !the order of the finite-difference gradient (fixed)
98 : !calculate the dimensions wrt the geocode
99 :
100 31829 : IF (geocode == 'P') THEN
101 16561 : CALL P_FFT_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
102 15268 : ELSE IF (geocode == 'S') THEN
103 18 : CALL S_FFT_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
104 15250 : ELSE IF (geocode == 'F') THEN
105 15250 : CALL F_FFT_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
106 : ELSE
107 0 : CPABORT("PSolver: geometry code not admitted")
108 : END IF
109 : !array allocations
110 159145 : ALLOCATE (zf(md1, md3, md2/nproc))
111 :
112 : ! CALL timing(iproc,'Exchangecorr ','ON')
113 : !dimension for exchange-correlation (different in the global or distributed case)
114 : !let us calculate the dimension of the portion of the rhopot array to be passed
115 : !to the xc routine
116 : !this portion will depend on the need of calculating the gradient or not,
117 : !and whether the White-Bird correction must be inserted or not
118 : !(absent only in the LB ixc=13 case)
119 :
120 : !nxc is the effective part of the third dimension that is being processed
121 : !nxt is the dimension of the part of rhopot that must be passed to the gradient routine
122 : !nwb is the dimension of the part of rhopot in the wb-postprocessing routine
123 : !note: nxc <= nwb <= nxt
124 : !the dimension are related by the values of nwbl and nwbr
125 : ! nxc+nxcl+nxcr-2 = nwb
126 : ! nwb+nwbl+nwbr = nxt
127 31829 : istart = iproc*(md2/nproc)
128 31829 : iend = MIN((iproc + 1)*md2/nproc, m2)
129 :
130 31829 : nxc = iend - istart
131 31829 : nwbl = 0
132 31829 : nwbr = 0
133 31829 : nxcl = 1
134 31829 : nxcr = 1
135 :
136 31829 : nwb = nxcl + nxc + nxcr - 2
137 31829 : nxt = nwbr + nwb + nwbl
138 :
139 : !calculate the actual limit of the array for the zero padded FFT
140 31829 : IF (geocode == 'P') THEN
141 16561 : nlim = n2
142 15268 : ELSE IF (geocode == 'S') THEN
143 18 : nlim = n2
144 15250 : ELSE IF (geocode == 'F') THEN
145 15250 : nlim = n2/2
146 : END IF
147 :
148 : !!$ print *,'density must go from',min(istart+1,m2),'to',iend,'with n2/2=',n2/2
149 : !!$ print *,' it goes from',i3start+nwbl+nxcl-1,'to',i3start+nxc-1
150 :
151 31829 : IF (istart + 1 <= m2) THEN
152 31829 : red_fact = 1._dp
153 31829 : CALL scale_and_distribute(m1, m3, md1, md2, md3, nxc, rhopot, zf, nproc, red_fact)
154 0 : ELSE IF (istart + 1 <= nlim) THEN !this condition assures that we have perform good zero padding
155 0 : DO i2 = istart + 1, MIN(nlim, istart + md2/nproc)
156 0 : j2 = i2 - istart
157 0 : DO i3 = 1, md3
158 0 : DO i1 = 1, md1
159 0 : zf(i1, i3, j2) = 0._dp
160 : END DO
161 : END DO
162 : END DO
163 : END IF
164 :
165 : !this routine builds the values for each process of the potential (zf), multiplying by scal
166 31829 : IF (geocode == 'P') THEN
167 : !no powers of hgrid because they are incorporated in the plane wave treatment
168 16561 : scal = 1._dp/REAL(n1*n2*n3, KIND=dp)
169 : CALL P_PoissonSolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, zf, &
170 16561 : scal, hx, hy, hz, pw_grid%para%group)
171 15268 : ELSE IF (geocode == 'S') THEN
172 : !only one power of hgrid
173 18 : scal = hy/REAL(n1*n2*n3, KIND=dp)
174 : CALL S_PoissonSolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, karray, zf, &
175 18 : scal, pw_grid%para%group)
176 15250 : ELSE IF (geocode == 'F') THEN
177 15250 : hgrid = MAX(hx, hy, hz)
178 15250 : scal = hgrid**3/REAL(n1*n2*n3, KIND=dp)
179 : CALL F_PoissonSolver(n1, n2, n3, nd1, nd2, nd3, md1, md2, md3, nproc, iproc, karray, zf, &
180 15250 : scal, pw_grid%para%group)
181 15250 : factor = 0.5_dp*hgrid**3
182 : END IF
183 :
184 : ! call timing(iproc,'PSolv_comput ','ON')
185 :
186 : !the value of the shift depends on the distributed i/o or not
187 31829 : IF (geocode == 'F') THEN
188 15250 : red_fact = 1._dp
189 : ELSE
190 16579 : red_fact = -fourpi
191 : END IF
192 :
193 31829 : CALL scale_and_distribute(m1, m3, md1, md2, md3, nxc, zf, rhopot, nproc, red_fact)
194 :
195 31829 : DEALLOCATE (zf)
196 :
197 31829 : END SUBROUTINE PSolver
198 :
199 : ! **************************************************************************************************
200 : !> \brief Calculate four sets of dimension needed for the calculation of the
201 : !> convolution for the periodic system
202 : !> \param n01 original real dimensions (input)
203 : !> \param n02 original real dimensions (input)
204 : !> \param n03 original real dimensions (input)
205 : !> \param m1 original real dimension, with m2 and m3 exchanged
206 : !> \param m2 original real dimension, with m2 and m3 exchanged
207 : !> \param m3 original real dimension, with m2 and m3 exchanged
208 : !> \param n1 the first FFT dimensions, for the moment supposed to be even
209 : !> \param n2 the first FFT dimensions, for the moment supposed to be even
210 : !> \param n3 the first FFT dimensions, for the moment supposed to be even
211 : !> \param md1 the n1,n2,n3 dimensions. They contain the real unpadded space,
212 : !> properly enlarged to be compatible with the FFT dimensions n_i.
213 : !> md2 is further enlarged to be a multiple of nproc
214 : !> \param md2 the n1,n2,n3 dimensions. They contain the real unpadded space,
215 : !> properly enlarged to be compatible with the FFT dimensions n_i.
216 : !> md2 is further enlarged to be a multiple of nproc
217 : !> \param md3 the n1,n2,n3 dimensions. They contain the real unpadded space,
218 : !> properly enlarged to be compatible with the FFT dimensions n_i.
219 : !> md2 is further enlarged to be a multiple of nproc
220 : !> \param nd1 fourier dimensions for which the kernel is injective,
221 : !> formally 1/8 of the fourier grid. Here the dimension nd3 is
222 : !> enlarged to be a multiple of nproc
223 : !> \param nd2 fourier dimensions for which the kernel is injective,
224 : !> formally 1/8 of the fourier grid. Here the dimension nd3 is
225 : !> enlarged to be a multiple of nproc
226 : !> \param nd3 fourier dimensions for which the kernel is injective,
227 : !> formally 1/8 of the fourier grid. Here the dimension nd3 is
228 : !> enlarged to be a multiple of nproc
229 : !> \param nproc ...
230 : !> \date October 2006
231 : !> \author Luigi Genovese
232 : !> \note This four sets of dimensions are actually redundant (mi=n0i),
233 : !> due to the backward-compatibility
234 : !> with the other geometries of the Poisson Solver.
235 : !> The dimensions 2 and 3 are exchanged.
236 : ! **************************************************************************************************
237 50619 : SUBROUTINE P_FFT_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
238 : INTEGER, INTENT(in) :: n01, n02, n03
239 : INTEGER, INTENT(out) :: m1, m2, m3, n1, n2, n3, md1, md2, md3, &
240 : nd1, nd2, nd3
241 : INTEGER, INTENT(in) :: nproc
242 :
243 : INTEGER :: l1, l2, l3
244 :
245 : !dimensions of the density in the real space
246 :
247 16873 : m1 = n01
248 16873 : m2 = n03
249 16873 : m3 = n02
250 :
251 : ! real space grid dimension (suitable for number of processors)
252 16873 : l1 = m1
253 16873 : l2 = m2
254 16873 : l3 = m3 !beware of the half dimension
255 16873 : CALL fourier_dim(l1, n1)
256 16873 : IF (n1 == m1) THEN
257 : ELSE
258 0 : PRINT *, 'the FFT in the x direction is not allowed'
259 0 : PRINT *, 'n01 dimension', n01
260 0 : CPABORT("")
261 : END IF
262 16873 : l1 = l1 + 1
263 16873 : CALL fourier_dim(l2, n2)
264 16873 : IF (n2 == m2) THEN
265 : ELSE
266 0 : PRINT *, 'the FFT in the z direction is not allowed'
267 0 : PRINT *, 'n03 dimension', n03
268 0 : CPABORT("")
269 : END IF
270 16873 : CALL fourier_dim(l3, n3)
271 16873 : IF (n3 == m3) THEN
272 : ELSE
273 0 : PRINT *, 'the FFT in the y direction is not allowed'
274 0 : PRINT *, 'n02 dimension', n02
275 0 : CPABORT("")
276 : END IF
277 :
278 : !dimensions that contain the unpadded real space,
279 : ! compatible with the number of processes
280 16873 : md1 = n1
281 16873 : md2 = n2
282 16873 : md3 = n3
283 18153 : DO WHILE (nproc*(md2/nproc) .LT. n2)
284 1280 : md2 = md2 + 1
285 : END DO
286 :
287 : !dimensions of the kernel, 1/8 of the total volume,
288 : !compatible with nproc
289 16873 : nd1 = n1/2 + 1
290 16873 : nd2 = n2/2 + 1
291 16873 : nd3 = n3/2 + 1
292 18703 : DO WHILE (MODULO(nd3, nproc) .NE. 0)
293 1830 : nd3 = nd3 + 1
294 : END DO
295 :
296 16873 : END SUBROUTINE P_FFT_dimensions
297 :
298 : ! **************************************************************************************************
299 : !> \brief Calculate four sets of dimension needed for the calculation of the
300 : !> convolution for the surface system
301 : !> \param n01 original real dimensions (input)
302 : !> \param n02 original real dimensions (input)
303 : !> \param n03 original real dimensions (input)
304 : !> \param m1 original real dimension, with 2 and 3 exchanged
305 : !> \param m2 original real dimension, with 2 and 3 exchanged
306 : !> \param m3 original real dimension, with 2 and 3 exchanged
307 : !> \param n1 the first FFT dimensions, for the moment supposed to be even
308 : !> \param n2 the first FFT dimensions, for the moment supposed to be even
309 : !> \param n3 the double of the first FFT even dimension greater than m3
310 : !> (improved for the HalFFT procedure)
311 : !> \param md1 the n1,n2 dimensions.
312 : !> \param md2 the n1,n2,n3 dimensions.
313 : !> \param md3 the half of n3 dimension. They contain the real unpadded space,
314 : !> properly enlarged to be compatible with the FFT dimensions n_i.
315 : !> md2 is further enlarged to be a multiple of nproc
316 : !> \param nd1 fourier dimensions for which the kernel is injective,
317 : !> formally 1/8 of the fourier grid. Here the dimension nd3 is
318 : !> enlarged to be a multiple of nproc
319 : !> \param nd2 fourier dimensions for which the kernel is injective,
320 : !> formally 1/8 of the fourier grid. Here the dimension nd3 is
321 : !> enlarged to be a multiple of nproc
322 : !> \param nd3 fourier dimensions for which the kernel is injective,
323 : !> formally 1/8 of the fourier grid. Here the dimension nd3 is
324 : !> enlarged to be a multiple of nproc
325 : !> \param nproc ...
326 : !> \date October 2006
327 : !> \author Luigi Genovese
328 : !> \note This four sets of dimensions are actually redundant (mi=n0i),
329 : !> due to the backward-compatibility
330 : !> with the Poisson Solver with other geometries.
331 : !> Dimensions n02 and n03 were exchanged
332 : ! **************************************************************************************************
333 66 : SUBROUTINE S_FFT_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
334 : INTEGER, INTENT(in) :: n01, n02, n03
335 : INTEGER, INTENT(out) :: m1, m2, m3, n1, n2, n3, md1, md2, md3, &
336 : nd1, nd2, nd3
337 : INTEGER, INTENT(in) :: nproc
338 :
339 : CHARACTER(len=*), PARAMETER :: routineN = 'S_FFT_dimensions'
340 :
341 : INTEGER :: handle, l1, l2, l3
342 :
343 : !dimensions of the density in the real space
344 :
345 22 : CALL timeset(routineN, handle)
346 22 : m1 = n01
347 22 : m2 = n03
348 22 : m3 = n02
349 :
350 : ! real space grid dimension (suitable for number of processors)
351 22 : l1 = m1
352 22 : l2 = m2
353 22 : l3 = m3 !beware of the half dimension
354 22 : CALL fourier_dim(l1, n1)
355 22 : IF (n1 == m1) THEN
356 : ELSE
357 0 : PRINT *, 'the FFT in the x direction is not allowed'
358 0 : PRINT *, 'n01 dimension', n01
359 0 : CPABORT("")
360 : END IF
361 22 : l1 = l1 + 1
362 22 : CALL fourier_dim(l2, n2)
363 22 : IF (n2 == m2) THEN
364 : ELSE
365 0 : PRINT *, 'the FFT in the z direction is not allowed'
366 0 : PRINT *, 'n03 dimension', n03
367 0 : CPABORT("")
368 : END IF
369 22 : DO
370 22 : CALL fourier_dim(l3, n3)
371 22 : IF (MODULO(n3, 2) == 0) THEN
372 : EXIT
373 : END IF
374 0 : l3 = l3 + 1
375 : END DO
376 22 : n3 = 2*n3
377 :
378 : !dimensions that contain the unpadded real space,
379 : ! compatible with the number of processes
380 22 : md1 = n1
381 22 : md2 = n2
382 22 : md3 = n3/2
383 22 : DO WHILE (nproc*(md2/nproc) .LT. n2)
384 0 : md2 = md2 + 1
385 : END DO
386 :
387 : !dimensions of the kernel, 1/8 of the total volume,
388 : !compatible with nproc
389 :
390 : !these two dimensions are like that since they are even
391 22 : nd1 = n1/2 + 1
392 22 : nd2 = n2/2 + 1
393 :
394 22 : nd3 = n3/2 + 1
395 44 : DO WHILE (MODULO(nd3, nproc) .NE. 0)
396 22 : nd3 = nd3 + 1
397 : END DO
398 22 : CALL timestop(handle)
399 :
400 22 : END SUBROUTINE S_FFT_dimensions
401 :
402 : ! **************************************************************************************************
403 : !> \brief Calculate four sets of dimension needed for the calculation of the
404 : !> zero-padded convolution
405 : !> \param n01 original real dimensions (input)
406 : !> \param n02 original real dimensions (input)
407 : !> \param n03 original real dimensions (input)
408 : !> \param m1 original real dimension with the dimension 2 and 3 exchanged
409 : !> \param m2 original real dimension with the dimension 2 and 3 exchanged
410 : !> \param m3 original real dimension with the dimension 2 and 3 exchanged
411 : !> \param n1 ...
412 : !> \param n2 ...
413 : !> \param n3 the double of the first FFT even dimension greater than m3
414 : !> (improved for the HalFFT procedure)
415 : !> \param md1 half of n1,n2,n3 dimension. They contain the real unpadded space,
416 : !> properly enlarged to be compatible with the FFT dimensions n_i.
417 : !> md2 is further enlarged to be a multiple of nproc
418 : !> \param md2 half of n1,n2,n3 dimension. They contain the real unpadded space,
419 : !> properly enlarged to be compatible with the FFT dimensions n_i.
420 : !> md2 is further enlarged to be a multiple of nproc
421 : !> \param md3 half of n1,n2,n3 dimension. They contain the real unpadded space,
422 : !> properly enlarged to be compatible with the FFT dimensions n_i.
423 : !> md2 is further enlarged to be a multiple of nproc
424 : !> \param nd1 fourier dimensions for which the kernel FFT is injective,
425 : !> formally 1/8 of the fourier grid. Here the dimension nd3 is
426 : !> enlarged to be a multiple of nproc
427 : !> \param nd2 fourier dimensions for which the kernel FFT is injective,
428 : !> formally 1/8 of the fourier grid. Here the dimension nd3 is
429 : !> enlarged to be a multiple of nproc
430 : !> \param nd3 fourier dimensions for which the kernel FFT is injective,
431 : !> formally 1/8 of the fourier grid. Here the dimension nd3 is
432 : !> enlarged to be a multiple of nproc
433 : !> \param nproc ...
434 : !> \date February 2006
435 : !> \author Luigi Genovese
436 : !> \note The dimension m2 and m3 correspond to n03 and n02 respectively
437 : !> this is needed since the convolution routine manage arrays of dimension
438 : !> (md1,md3,md2/nproc)
439 : ! **************************************************************************************************
440 16594 : SUBROUTINE F_FFT_dimensions(n01, n02, n03, m1, m2, m3, n1, n2, n3, md1, md2, md3, nd1, nd2, nd3, nproc)
441 : INTEGER, INTENT(in) :: n01, n02, n03
442 : INTEGER, INTENT(out) :: m1, m2, m3, n1, n2, n3, md1, md2, md3, &
443 : nd1, nd2, nd3
444 : INTEGER, INTENT(in) :: nproc
445 :
446 : INTEGER :: l1, l2, l3
447 :
448 : !dimensions of the density in the real space, inverted for convenience
449 :
450 16594 : m1 = n01
451 16594 : m2 = n03
452 16594 : m3 = n02
453 : ! real space grid dimension (suitable for number of processors)
454 16594 : l1 = 2*m1
455 16594 : l2 = 2*m2
456 16594 : l3 = m3 !beware of the half dimension
457 16594 : DO
458 16594 : CALL fourier_dim(l1, n1)
459 16594 : IF (MODULO(n1, 2) == 0) THEN
460 : EXIT
461 : END IF
462 16594 : l1 = l1 + 1
463 : END DO
464 16594 : DO
465 16594 : CALL fourier_dim(l2, n2)
466 16594 : IF (MODULO(n2, 2) == 0) THEN
467 : EXIT
468 : END IF
469 16594 : l2 = l2 + 1
470 : END DO
471 26268 : DO
472 26268 : CALL fourier_dim(l3, n3)
473 26268 : IF (MODULO(n3, 2) == 0) THEN
474 : EXIT
475 : END IF
476 9674 : l3 = l3 + 1
477 : END DO
478 16594 : n3 = 2*n3
479 :
480 : !dimensions that contain the unpadded real space,
481 : ! compatible with the number of processes
482 16594 : md1 = n1/2
483 16594 : md2 = n2/2
484 16594 : md3 = n3/2
485 18850 : DO WHILE (nproc*(md2/nproc) .LT. n2/2)
486 2256 : md2 = md2 + 1
487 : END DO
488 :
489 : !dimensions of the kernel, 1/8 of the total volume,
490 : !compatible with nproc
491 16594 : nd1 = n1/2 + 1
492 16594 : nd2 = n2/2 + 1
493 16594 : nd3 = n3/2 + 1
494 :
495 25134 : DO WHILE (MODULO(nd3, nproc) .NE. 0)
496 8540 : nd3 = nd3 + 1
497 : END DO
498 :
499 16594 : END SUBROUTINE F_FFT_dimensions
500 :
501 : ! **************************************************************************************************
502 : !> \brief ...
503 : !> \param m1 ...
504 : !> \param m3 ...
505 : !> \param md1 ...
506 : !> \param md2 ...
507 : !> \param md3 ...
508 : !> \param nxc ...
509 : !> \param rhopot ...
510 : !> \param zf ...
511 : !> \param nproc ...
512 : !> \param factor ...
513 : ! **************************************************************************************************
514 63658 : SUBROUTINE scale_and_distribute(m1, m3, md1, md2, md3, nxc, &
515 63658 : rhopot, zf, nproc, factor)
516 :
517 : !Arguments----------------------
518 : INTEGER, INTENT(in) :: m1, m3, md1, md2, md3, nxc, nproc
519 : REAL(KIND=dp), DIMENSION(md1, md3, md2/nproc), &
520 : INTENT(inout) :: zf, rhopot
521 : REAL(KIND=dp), INTENT(in) :: factor
522 :
523 : CHARACTER(len=*), PARAMETER :: routineN = 'scale_and_distribute'
524 :
525 : INTEGER :: handle, j1, j3, jp2
526 :
527 63658 : CALL timeset(routineN, handle)
528 :
529 63658 : IF (nxc .GE. 1) THEN
530 1425262 : DO jp2 = 1, nxc
531 45595012 : DO j3 = 1, m3
532 1785335080 : DO j1 = 1, m1
533 1785335080 : zf(j1, j3, jp2) = factor*rhopot(j1, j3, jp2)
534 : END DO
535 50473762 : DO j1 = m1 + 1, md1
536 49112158 : zf(j1, j3, jp2) = 0._dp
537 : END DO
538 : END DO
539 2120392 : DO j3 = m3 + 1, md3
540 26788674 : DO j1 = 1, md1
541 25427070 : zf(j1, j3, jp2) = 0._dp
542 : END DO
543 : END DO
544 : END DO
545 74124 : DO jp2 = nxc + 1, md2/nproc
546 399092 : DO j3 = 1, md3
547 10234758 : DO j1 = 1, md1
548 10224292 : zf(j1, j3, jp2) = 0._dp
549 : END DO
550 : END DO
551 : END DO
552 : ELSE
553 0 : zf = 0._dp
554 : END IF
555 63658 : CALL timestop(handle)
556 :
557 63658 : END SUBROUTINE scale_and_distribute
558 : END MODULE ps_wavelet_util
|