SCALE-RM
scale_dft.F90
Go to the documentation of this file.
1 #include "scalelib.h"
2 ! special 2D-DFT routines for low wavenumber spectral transform
3 module scale_dft
4  use mpi
6  use scale_prc, only: &
9  use scale_prc_cartesc, only: &
10  prc_num_x, &
11  prc_num_y, &
13  use scale_comm_cartesc, only: &
15  use scale_const, only: &
16  pi => const_pi
17  implicit none
18 
19  public :: dft_setup
20  public :: dft_finalize
21  public :: dft_g2g
22  public :: dft_g2g_divfree
23 
24  integer, private :: IMAX, JMAX ! number of total grids for spectral transform
25  integer, private :: IGS, JGS ! global index
26  integer, private :: LMM, MMM ! maximum truncation wavenumber
27 
28  ! table for trigonometric function
29  real(RP), private, allocatable :: table_x(:,:), table_y(:,:)
30  real(RP), private, allocatable :: table_l(:), table_m(:)
31  ! work array
32  real(RP), private, allocatable :: work(:,:,:)
33 
34 contains
35 
36  subroutine dft_setup(KA,KS,KE,IA,IS,IE,JA,JS,JE,LM,MM)
37  implicit none
38  integer,intent(in) :: ka, ia, ja
39  integer,intent(in) :: ks, ke, is, ie, js, je
40  integer,intent(in) :: lm, mm
41  real(rp) :: x, y
42  integer :: i, j, k, l, m
43 
44  imax = (ie-is+1)*prc_num_x
45  jmax = (je-js+1)*prc_num_y
46 
47  igs = (ie-is+1)*prc_2drank(prc_myrank,1)+1
48  jgs = (je-js+1)*prc_2drank(prc_myrank,2)+1
49 
50  lmm = lm
51  mmm = mm
52 
53  allocate( table_x(is:ie,0:2*lm), table_y(js:je,0:2*mm) )
54  allocate( table_l(0:2*lm), table_m(0:2*mm) )
55  allocate( work(ka,0:2*lm,ja) )
56 
57  do i = is, ie
58  x = 2*pi/imax*(i-is+igs)
59  table_x(i,0) = 1
60  enddo
61 
62  do l = 1, lm
63  do i = is, ie
64  x = 2*pi/imax*(i-is+igs)
65  table_x(i,2*l-1) = cos(l*x)
66  table_x(i,2*l) = -sin(l*x)
67  enddo
68  enddo
69 
70  do j = js, je
71  y = 2*pi/jmax*(j-js+jgs)
72  table_y(j,0) = 1
73  enddo
74 
75  do m = 1, mm
76  do j = js, je
77  y = 2*pi/jmax*(j-js+jgs)
78  table_y(j,2*m-1) = cos(m*y)
79  table_y(j,2*m) = -sin(m*y)
80  enddo
81  enddo
82 
83  table_l(0) = 1
84  do l = 1, lm
85  table_l(2*l-1) = cos(pi*l/imax)
86  table_l(2*l) = sin(pi*l/imax)
87  enddo
88 
89  table_m(0) = 1
90  do m = 1, mm
91  table_m(2*m-1) = cos(pi*m/jmax)
92  table_m(2*m) = sin(pi*m/jmax)
93  enddo
94 
95  !$acc enter data copyin(table_x, table_y)
96  !$acc enter data copyin(table_l, table_m)
97  !$acc enter data create(work)
98 
99  end subroutine dft_setup
100 
101  subroutine dft_finalize
102 
103  !$acc exit data delete(table_x, table_y)
104  !$acc exit data delete(table_l, table_m)
105  !$acc exit data delete(work)
106  deallocate( table_x, table_y )
107  deallocate( table_l, table_m )
108  deallocate( work )
109 
110  return
111  end subroutine dft_finalize
112 
113  subroutine dft_g2s(KA,KS,KE,IA,IS,IE,JA,JS,JE,LM,MM,f,s)
114  ! Grid to spectral transformation
115  integer,intent(in) :: KA, IA, JA
116  integer,intent(in) :: KS, KE, IS, IE, JS, JE
117  integer,intent(in) :: LM, MM
118  real(RP), intent(in) :: f(KA, IA, JA) ! x: full level, y: full level
119  real(RP), intent(out) :: s(KA,0:2*LM,0:2*MM)
120  real(RP) :: work_s(KA,0:2*LM,0:2*MM)
121  real(RP) :: c, tb
122  integer :: i, j, k, l, m
123  integer :: ierr
124 
125  !$acc data copyin(f) copyout(s) create(work_s)
126 
127  c = 1.0_rp/imax
128  !$acc kernels
129  do j = js, je
130  do l = 0, 2*lm
131  do k = ks, ke
132  work(k,l,j) = 0
133  enddo
134  !$acc loop seq
135  do i = is, ie
136  tb = table_x(i,l)*c
137  do k = ks, ke
138  work(k,l,j) = work(k,l,j) + f(k,i,j)*tb
139  enddo
140  enddo
141  enddo
142  enddo
143  !$acc end kernels
144 
145  !$acc kernels
146  do m = 0, 2*mm
147  do l = 0, 2*lm
148  do k = ks, ke
149  work_s(k,l,m) = 0
150  enddo
151  enddo
152  enddo
153  !$acc end kernels
154 
155  c = 1.0_rp/jmax
156  !$acc kernels
157  do m = 0, 2*mm
158  do j = js, je
159  tb = table_y(j,m)*c
160  do l = 0, 2*lm
161  do k = ks, ke
162  !$acc atomic
163  work_s(k,l,m) = work_s(k,l,m) + work(k,l,j)*tb
164  enddo
165  enddo
166  enddo
167  enddo
168  !$acc end kernels
169 
170  call mpi_allreduce(work_s, s, ka*(2*lm+1)*(2*mm+1), comm_datatype, mpi_sum, prc_local_comm_world, ierr)
171 
172  !$acc end data
173 
174  end subroutine dft_g2s
175 
176  subroutine dft_s2g(KA,KS,KE,IA,IS,IE,JA,JS,JE,LM,MM,s,f)
177  ! Grid to spectral transformation
178  integer,intent(in) :: KA, IA, JA
179  integer,intent(in) :: KS, KE, IS, IE, JS, JE
180  integer,intent(in) :: LM, MM
181  real(RP), intent(in) :: s(KA,0:2*LM,0:2*MM)
182  real(RP), intent(out) :: f(KA, IA, JA) ! x: full level, y: full level
183  real(RP) :: c, tb
184  integer :: i, j, k, l, m
185 
186  !$acc data copyin(s) copyout(f)
187 
188  !$acc kernels
189  do j = js, je
190  do i = is, ie
191  do k = ks, ke
192  f(k,i,j) = 0
193  enddo
194  enddo
195  enddo
196  !$acc end kernels
197 
198  !$acc kernels
199  do j = js, je
200  do l = 0, 2*lm
201  do k = ks, ke
202  work(k,l,j) = 0
203  enddo
204  enddo
205  enddo
206  !$acc end kernels
207 
208  !$acc kernels
209  do m = 0, 2*mm
210  if( m == 0 ) then
211  c = 1
212  else
213  c = 2
214  endif
215  do j = js, je
216  tb = table_y(j,m)*c
217  do l = 0, 2*lm
218  do k = ks, ke
219  !$acc atomic
220  work(k,l,j) = work(k,l,j) + s(k,l,m)*tb
221  enddo
222  enddo
223  enddo
224  enddo
225  !$acc end kernels
226 
227  !$acc kernels
228  do j = js, je
229  do i = is, ie
230  do k = ks, ke
231  f(k,i,j) = 0
232  enddo
233  enddo
234  do l = 0, 2*lm
235  if( l == 0 ) then
236  c = 1
237  else
238  c = 2
239  endif
240  do i = is, ie
241  tb = table_x(i,l)*c
242  do k = ks, ke
243  !$acc atomic
244  f(k,i,j) = f(k,i,j) + work(k,l,j)*tb
245  enddo
246  enddo
247  enddo
248  enddo
249  !$acc end kernels
250 
251  !$acc end data
252 
253  end subroutine dft_s2g
254 
255  ! Grid to Grid transformation
256  subroutine dft_g2g(KA,KS,KE,IA,IS,IE,JA,JS,JE,LM,MM,f)
257  integer,intent(in) :: ka, ia, ja
258  integer,intent(in) :: ks, ke, is, ie, js, je
259  integer,intent(in) :: lm, mm
260  real(rp), intent(inout) :: f(ka, ia, ja) ! x,y: full or half level
261  real(rp) :: s(ka,0:2*lm,0:2*mm)
262 
263  call dft_g2s(ka,ks,ke,ia,is,ie,ja,js,je,lm,mm,f,s)
264  call dft_s2g(ka,ks,ke,ia,is,ie,ja,js,je,lm,mm,s,f)
265 
266  end subroutine dft_g2g
267 
268  ! Grid to Grid transformation of vector field with horizontal divergence filter
269  subroutine dft_g2g_divfree(KA,KS,KE,IA,IS,IE,JA,JS,JE,LM,MM,u,v)
270  integer,intent(in) :: ka, ia, ja
271  integer,intent(in) :: ks, ke, is, ie, js, je
272  integer,intent(in) :: lm, mm
273  real(rp), intent(inout) :: u(ka, ia, ja) ! x: half level, y: full level
274  real(rp), intent(inout) :: v(ka, ia, ja) ! x: full level, y: half level
275  integer :: k, l, m
276  real(rp) :: s1(ka,0:2*lm,0:2*mm)
277  real(rp) :: s2(ka,0:2*lm,0:2*mm)
278  real(rp) :: s3(ka,0:2*lm,0:2*mm)
279  real(rp) :: a, b, fac
280 
281  !$acc data copy(u,v) create(s1,s2,s3)
282 
283  call dft_g2s(ka,ks,ke,ia,is,ie,ja,js,je,lm,mm,u,s1)
284 
285  ! phase shift
286  !$acc kernels
287  do m = 0, 2*mm
288  do l = 1, lm
289  do k = ks, ke
290  a = s1(k,2*l-1,m)
291  b = s1(k,2*l,m)
292  s1(k,2*l-1,m) = a*table_l(2*l-1) + b*table_l(2*l)
293  s1(k,2*l,m) = b*table_l(2*l-1) - a*table_l(2*l)
294  enddo
295  enddo
296  enddo
297  !$acc end kernels
298 
299  call dft_g2s(ka,ks,ke,ia,is,ie,ja,js,je,lm,mm,v,s2)
300 
301  ! phase shift
302  !$acc kernels
303  do m = 1, mm
304  do l = 0, 2*lm
305  do k = ks, ke
306  a = s2(k,l,2*m-1)
307  b = s2(k,l,2*m)
308  s2(k,l,2*m-1) = a*table_m(2*m-1) + b*table_m(2*m)
309  s2(k,l,2*m) = b*table_m(2*m-1) - a*table_m(2*m)
310  enddo
311  enddo
312  enddo
313  !$acc end kernels
314 
315  ! rotation
316  !$acc kernels
317  do m = 0, 2*mm
318  do l = 0, 2*lm
319  do k = ks, ke
320  s3(k,l,m) = 0
321  enddo
322  enddo
323  enddo
324  !$acc end kernels
325 
326  ! dv/dx
327  !$acc kernels
328  do m = 0, 2*mm
329  do l = 1, lm
330  do k = ks, ke
331  s3(k,2*l-1,m) = -l*s2(k,2*l,m)
332  s3(k,2*l,m) = l*s2(k,2*l-1,m)
333  enddo
334  enddo
335  enddo
336  !$acc end kernels
337 
338  ! + (- du/dy)
339  !$acc kernels
340  do m = 1, mm
341  do l = 0, 2*lm
342  do k = ks, ke
343  s3(k,l,2*m-1) = s3(k,l,2*m-1) + m*s1(k,l,2*m)
344  s3(k,l,2*m) = s3(k,l,2*m) - m*s1(k,l,2*m-1)
345  enddo
346  enddo
347  enddo
348  !$acc end kernels
349 
350  ! minus inverse laplacian ( stream function on model plane )
351  !$acc kernels
352  do k = ks, ke
353  s3(k,0,0) = 0
354  enddo
355  !$acc end kernels
356 
357  !$acc kernels
358  do l = 1, lm
359  fac = 1.0_rp/ (l*l)
360  do k = ks, ke
361  s3(k,2*l-1,0) = s3(k,2*l-1,0)*fac
362  s3(k,2*l,0) = s3(k,2*l,0)*fac
363  enddo
364  enddo
365  !$acc end kernels
366 
367  !$acc kernels
368  do m = 1, mm
369  fac = 1.0_rp/ (m*m)
370  do k = ks, ke
371  s3(k,0,2*m-1) = s3(k,0,2*m-1)*fac
372  s3(k,0,2*m) = s3(k,0,2*m)*fac
373  enddo
374  enddo
375  !$acc end kernels
376 
377  !$acc kernels
378  do m = 1, mm
379  do l = 1, lm
380  fac = 1.0_rp/ (l*l+m*m)
381  do k = ks, ke
382  s3(k,2*l-1,2*m-1) = s3(k,2*l-1,2*m-1)*fac
383  s3(k,2*l-1,2*m) = s3(k,2*l-1,2*m)*fac
384  s3(k,2*l,2*m-1) = s3(k,2*l,2*m-1)*fac
385  s3(k,2*l,2*m) = s3(k,2*l,2*m)*fac
386  enddo
387  enddo
388  enddo
389  !$acc end kernels
390 
391  ! divergence free 2D vector
392 
393  ! dphi/dy
394  !$acc kernels
395  do l = 1, 2*lm
396  do k = ks, ke
397  s1(k,l,0) = 0
398  enddo
399  enddo
400  !$acc end kernels
401  !$acc kernels
402  do m = 1, mm
403  do l = 0, 2*lm
404  do k = ks, ke
405  s1(k,l,2*m-1) = -m*s3(k,l,2*m)
406  s1(k,l,2*m) = m*s3(k,l,2*m-1)
407  enddo
408  enddo
409  enddo
410  !$acc end kernels
411 
412  ! -dphi/dx
413  !$acc kernels
414  do m = 1, 2*mm
415  do k = ks, ke
416  s2(k,0,m) = 0
417  enddo
418  enddo
419  !$acc end kernels
420  !$acc kernels
421  do m = 0, 2*mm
422  do l = 1, lm
423  do k = ks, ke
424  s2(k,2*l-1,m) = l*s3(k,2*l,m)
425  s2(k,2*l,m) = -l*s3(k,2*l-1,m)
426  enddo
427  enddo
428  enddo
429  !$acc end kernels
430 
431  ! phase shift
432  !$acc kernels
433  do m = 0, 2*mm
434  do l = 1, lm
435  do k = ks, ke
436  a = s1(k,2*l-1,m)
437  b = s1(k,2*l,m)
438  s1(k,2*l-1,m) = a*table_l(2*l-1) - b*table_l(2*l)
439  s1(k,2*l,m) = b*table_l(2*l-1) + a*table_l(2*l)
440  enddo
441  enddo
442  enddo
443  !$acc end kernels
444 
445  call dft_s2g(ka,ks,ke,ia,is,ie,ja,js,je,lm,mm,s1,u)
446 
447  ! phase shift
448  !$acc kernels
449  do m = 1, mm
450  do l = 0, 2*lm
451  do k = ks, ke
452  a = s2(k,l,2*m-1)
453  b = s2(k,l,2*m)
454  s2(k,l,2*m-1) = a*table_m(2*m-1) - b*table_m(2*m)
455  s2(k,l,2*m) = b*table_m(2*m-1) + a*table_m(2*m)
456  enddo
457  enddo
458  enddo
459  !$acc end kernels
460 
461  call dft_s2g(ka,ks,ke,ia,is,ie,ja,js,je,lm,mm,s2,v)
462 
463  !$acc end data
464 
465  end subroutine dft_g2g_divfree
466 
467 end module scale_dft
scale_dft::dft_finalize
subroutine, public dft_finalize
Definition: scale_dft.F90:102
scale_comm_cartesc::comm_datatype
integer, public comm_datatype
datatype of variable
Definition: scale_comm_cartesC.F90:105
scale_dft::dft_g2s
subroutine dft_g2s(KA, KS, KE, IA, IS, IE, JA, JS, JE, LM, MM, f, s)
Definition: scale_dft.F90:114
scale_precision
module PRECISION
Definition: scale_precision.F90:14
scale_prc::prc_local_comm_world
integer, public prc_local_comm_world
local communicator
Definition: scale_prc.F90:89
scale_dft::dft_g2g_divfree
subroutine, public dft_g2g_divfree(KA, KS, KE, IA, IS, IE, JA, JS, JE, LM, MM, u, v)
Definition: scale_dft.F90:270
scale_prc::prc_myrank
integer, public prc_myrank
process num in local communicator
Definition: scale_prc.F90:91
scale_dft
Definition: scale_dft.F90:3
scale_prc
module PROCESS
Definition: scale_prc.F90:11
scale_const
module CONSTANT
Definition: scale_const.F90:11
scale_prc_cartesc::prc_2drank
integer, dimension(:,:), allocatable, public prc_2drank
node index in 2D topology
Definition: scale_prc_cartesC.F90:45
scale_prc_cartesc
module process / cartesC
Definition: scale_prc_cartesC.F90:11
scale_dft::dft_setup
subroutine, public dft_setup(KA, KS, KE, IA, IS, IE, JA, JS, JE, LM, MM)
Definition: scale_dft.F90:37
scale_dft::dft_g2g
subroutine, public dft_g2g(KA, KS, KE, IA, IS, IE, JA, JS, JE, LM, MM, f)
Definition: scale_dft.F90:257
scale_const::const_pi
real(rp), parameter, public const_pi
pi
Definition: scale_const.F90:32
scale_comm_cartesc
module COMMUNICATION
Definition: scale_comm_cartesC.F90:11
scale_prc_cartesc::prc_num_y
integer, public prc_num_y
y length of 2D processor topology
Definition: scale_prc_cartesC.F90:43
scale_prc_cartesc::prc_num_x
integer, public prc_num_x
x length of 2D processor topology
Definition: scale_prc_cartesC.F90:42
scale_dft::dft_s2g
subroutine dft_s2g(KA, KS, KE, IA, IS, IE, JA, JS, JE, LM, MM, s, f)
Definition: scale_dft.F90:177