FE-Project
Loading...
Searching...
No Matches
scale_meshfield_spectral_transform.F90
Go to the documentation of this file.
1!> module FElib / Data / Utility
2!!
3!! @par Description
4!! A module for providing utility routines associated with spectral transformation for DG fields
5!! @author Yuta Kawai, Team SCALE
6!!
7!<
8#include "scaleFElib.h"
10 !-----------------------------------------------------------------------------
11 !
12 !++ used modules
13 !
14 use scale_precision
15 use scale_io
16 use scale_const, only: &
17 pi => const_pi
18 use scale_prc, only: &
19 prc_abort
20
21 use scale_polynomial, only: &
23 use scale_element_base, only: &
25 use scale_element_line, only: &
32
33 use scale_localmeshfield_base, only: &
36 use scale_meshfield_base, only: &
39
42 !-----------------------------------------------------------------------------
43 implicit none
44 private
45 !-----------------------------------------------------------------------------
46 !
47 !++ Public type & procedure
48 !
49
51 integer :: eval_type_id
52 integer :: ndim
53 integer :: var_num
54
55 real(rp), allocatable :: fftintrpmat(:,:)
56 real(rp), allocatable :: fft_xi(:)
57 integer :: nsampleptperelem
58
59 real(rp), allocatable :: intintrpmat(:,:)
60 real(rp), allocatable :: intweight(:)
61 real(rp), allocatable :: intxi(:)
62 integer :: nintglpt
64
65 !> A derived type for spectral transform of MeshField1D
67 integer :: kall
68 integer :: ks, ke
69
70 real(rp) :: xmin_gl, xmax_gl
71 real(rp) :: delx
72
73 real(rp), allocatable :: k(:)
74 real(rp), allocatable :: spectral_coef(:,:,:)
75
77 contains
78 procedure :: init => meshfield_spetraltransform1d_init
79 procedure :: final => meshfield_spetraltransform1d_final
80 procedure :: transform => meshfield_spetraltransform1d_transform
82
83 !> A derived type for spectral transform of MeshField2D
85 integer :: kall
86 integer :: ks, ke
87 integer :: lall
88 integer :: ls, le
89
90 real(rp) :: xmin_gl, xmax_gl
91 real(rp) :: delx
92 real(rp) :: ymin_gl, ymax_gl
93 real(rp) :: dely
94
95 integer :: nprcx
96 integer :: nprcy
97 integer :: negx, negy
98
99 integer :: nsampleptperelem1d
100
101 real(rp), allocatable :: k(:)
102 real(rp), allocatable :: l(:)
103 real(rp), allocatable :: spectral_coef(:,:,:,:)
104
107 contains
108 procedure :: init => meshfield_spetraltransform2d_init
109 procedure :: final => meshfield_spetraltransform2d_final
110 procedure :: transform => meshfield_spetraltransform2d_transform
112
113 !-----------------------------------------------------------------------------
114 !
115 !++ Public parameters & variables
116 !
117 integer, public, parameter :: st_evaltype_sample_uniform_pts = 1
118 integer, public, parameter :: st_evaltype_l2projection_1 = 2
119 integer, public, parameter :: st_evaltype_l2projection_2 = 3
120
121 !-----------------------------------------------------------------------------
122 !
123 !++ Private procedure
124 !
125
126 !-----------------------------------------------------------------------------
127 !
128 !++ Private parameters & variables
129 !
130 !-----------------------------------------------------------------------------
131
132contains
133!- Base type
134
135!OCL SERIAL
136 subroutine meshfield_spetraltransformbase_init( this, eval_type, ndim, var_num, NintGLpt, NsamplePtPerElem )
137 implicit none
138 class(meshfield_spetraltransformbase), intent(inout) :: this
139 integer, intent(in) :: eval_type
140 integer, intent(in) :: ndim
141 integer, intent(in) :: var_num
142 integer, intent(in), optional :: nintglpt
143 integer, intent(in), optional :: nsampleptperelem
144 !--------------------------------------------
145
146 this%eval_type_id = eval_type
147 call check_eval_type_id( eval_type )
148
149 this%ndim = ndim
150 this%var_num = var_num
151
152 if ( this%eval_type_id == st_evaltype_l2projection_1 &
153 .or. this%eval_type_id == st_evaltype_l2projection_2 ) then
154 if ( .not. present(nintglpt) ) then
155 log_info("MeshField_SpetralTransformBase_Init",*) "The order of Gaussian quadrature should be given. Check!"
156 call prc_abort
157 end if
158 this%NintGLPt = nintglpt
159 else
160 this%NintGLPt = -1
161 end if
162
163 if ( this%eval_type_id == st_evaltype_sample_uniform_pts ) then
164 if ( .not. present(nsampleptperelem) ) then
165 log_info("MeshField_SpetralTransformBase_Init",*) "NsamplePtPerElem shouled be given. Check!"
166 else
167 this%NsamplePtPerElem = nsampleptperelem
168 end if
169 else
170 this%NsamplePtPerElem = -1
171 end if
172 log_info("MeshField_SpetralTransformBase_Init",*) "NintGLPt=", this%NintGLpt, "NsamplePtPerElem=", this%NsamplePtPerElem
173
174 return
175 end subroutine meshfield_spetraltransformbase_init
176
177 subroutine check_eval_type_id( eval_type )
178 implicit none
179 integer, intent(in) :: eval_type
180 !-------------------------
181 select case(eval_type)
182! case(ST_EVALTYPE_L2PROJECTION_1,ST_EVALTYPE_L2PROJECTION_2,ST_EVALTYPE_SAMPLE_UNIFORM_PTS)
184 case default
185 log_info("MeshField_SpetralTransformBase_Init",*) "Unsupported evaluation type is specified. Check!"
186 call prc_abort
187 end select
188 return
189 end subroutine check_eval_type_id
190
191!OCL SERIAL
192 subroutine meshfield_spetraltransformbase_final( this )
193 implicit none
194 class(meshfield_spetraltransformbase), intent(inout) :: this
195 !--------------------------------------------
196
197 if ( this%NintGLpt > 0 ) &
198 deallocate( this%IntIntrpMat, this%IntXi, this%IntWeight )
199
200 if ( this%NsamplePtPerElem > 0 ) &
201 deallocate( this%FFTIntrpMat, this%FFT_xi )
202
203 return
204 end subroutine meshfield_spetraltransformbase_final
205
206!- 1D
207
208!OCL SERIAL
209 subroutine meshfield_spetraltransform1d_init( this, eval_type, ks, ke, mesh1D, var_num, &
210 GLQuadOrd, NsamplePtPerElem )
211 implicit none
212 class(meshfield_spetraltransform1d), intent(inout) :: this
213 integer, intent(in) :: eval_type
214 integer, intent(in) :: ks, ke
215 class(meshbase1d), intent(in), target :: mesh1d
216 integer, intent(in) :: var_num
217 integer, optional :: glquadord
218 integer, optional :: nsampleptperelem
219
220 integer :: i
221 integer :: lx
222 real(rp) :: dx
223
224 class(localmesh1d), pointer :: lmesh
225 class(elementbase1d), pointer :: elem
226
227 type(lineelement) :: elem_dummy
228 !--------------------------------------------
229
230 lmesh => mesh1d%lcmesh_list(1)
231 elem => lmesh%refElem1D
232
233 call meshfield_spetraltransformbase_init( this, eval_type, 1, var_num, &
234 glquadord, nsampleptperelem )
235
236 this%ks = ks; this%ke = ke
237 this%kall = ke - ks + 1
238
239 this%xmin_gl = mesh1d%xmin_gl
240 this%xmax_gl = mesh1d%xmax_gl
241 this%delx = 1.0_rp / real(mesh1d%NeG,kind=rp)
242
243 allocate( this%k(ks:ke) )
244 lx = this%xmax_gl - this%xmin_gl
245 do i=ks, ke
246 this%k(i) = i * 2.0_rp * pi / lx
247 end do
248
249 allocate( this%spectral_coef(ks:ke,2,var_num) )
250
251 call elem_dummy%Init(elem%PolyOrder, .false.)
252
253 if ( this%NintGLpt > 0 ) then
254 allocate( this%IntIntrpMat(this%NintGLpt,elem%Np) )
255 allocate( this%IntXi(this%NintGLpt), this%IntWeight(this%NintGLpt) )
256
257 this%IntIntrpMat(:,:) = elem_dummy%GenIntGaussLegendreIntrpMat( glquadord, this%IntWeight, this%IntXi )
258 end if
259
260 if ( this%NsamplePtPerElem > 0 ) then
261 allocate( this%FFTIntrpMat(this%NsamplePtPerElem,elem%Np) )
262 allocate( this%FFT_Xi(this%NsamplePtPerElem) )
263
264 dx = 2.0_rp / real(this%NsamplePtPerElem,kind=rp)
265 do i=1, this%NsamplePtPerElem
266 this%FFT_Xi(i) = -1.0_rp + real(i - 0.5_rp,kind=rp) * dx
267 end do
268 this%FFTIntrpMat(:,:) = polynomial_genlagrangepoly( elem_dummy%PolyOrder, elem_dummy%x1, this%FFT_xi )
269
270 call this%fft%Init( nsampleptperelem * mesh1d%NeG )
271 end if
272
273 call elem_dummy%Final()
274
275 return
276 end subroutine meshfield_spetraltransform1d_init
277
278!OCL SERIAL
279 subroutine meshfield_spetraltransform1d_final( this )
280 implicit none
281 class(meshfield_spetraltransform1d), intent(inout) :: this
282 !--------------------------------------------
283
284 call meshfield_spetraltransformbase_final( this )
285
286 if ( this%NsamplePtPerElem > 0 ) then
287 call this%fft%Final()
288 end if
289
290 deallocate( this%k, this%spectral_coef )
291
292 return
293 end subroutine meshfield_spetraltransform1d_final
294
295!OCL SERIAL
296 subroutine meshfield_spetraltransform1d_transform( this, q_list, mesh_num )
297 implicit none
298 class(meshfield_spetraltransform1d), intent(inout) :: this
299 integer, intent(in) :: mesh_num
300 type(meshfield1dlist), target :: q_list(this%var_num,mesh_num)
301
302 class(meshbase1d), pointer :: mesh1d
303 class(localmesh1d), pointer :: lmesh
304 !--------------------------------------------
305
306 mesh1d => q_list(1,1)%ptr%mesh
307 lmesh => mesh1d%lcmesh_list(1)
308
309 select case( this%eval_type_id )
311 call spectral_transform1d_dft( this%spectral_coef, & ! (out)
312 q_list, this%var_num, mesh_num, & ! (in)
313 this%ks, this%ke, lmesh%refElem1D%Np, lmesh%Ne, this%NsamplePtPerElem, & ! (in)
314 this%fft, this%FFTIntrpMat, this%FFT_xi, & ! (in)
315 this%xmin_gl, this%delx, this%xmax_gl - this%xmin_gl ) ! (in)
317 call spectral_transform1d_l2projection( this%spectral_coef, & ! (out)
318 q_list, this%var_num, mesh_num, & ! (in)
319 this%ks, this%ke, lmesh%refElem1D%Np, lmesh%Ne, & ! (in)
320 this%IntIntrpMat, this%IntXi, this%IntWeight, this%NintGLPt, & ! (in)
321 this%xmin_gl, this%delx, this%xmax_gl - this%xmin_gl ) ! (in)
322 end select
323
324 return
325 end subroutine meshfield_spetraltransform1d_transform
326
327!- 2D
328
329!OCL SERIAL
330 subroutine meshfield_spetraltransform2d_init( this, eval_type, ks, ke, ls, le, mesh2D, var_num, &
331 GLQuadOrd, NsamplePtPerElem1D )
332 use scale_element_line, only: &
334 use scale_mesh_rectdom2d, only: &
336 implicit none
337 class(meshfield_spetraltransform2d), intent(inout) :: this
338 integer, intent(in) :: eval_type
339 integer, intent(in) :: ks, ke
340 integer, intent(in) :: ls, le
341 class(meshbase2d), intent(in), target :: mesh2d
342 integer, intent(in) :: var_num
343 integer, optional :: glquadord
344 integer, optional :: nsampleptperelem1d
345
346 integer :: i, j
347 integer :: lx, ly
348 real(rp) :: dx
349
350 class(localmesh2d), pointer :: lmesh
351 class(elementbase2d), pointer :: elem
352
353 type(lineelement) :: elem_dummy
354 class(meshbase2d), pointer :: ptr_mesh2d
355 !--------------------------------------------
356
357 lmesh => mesh2d%lcmesh_list(1)
358 elem => lmesh%refElem2D
359
360 call meshfield_spetraltransformbase_init( this, eval_type, 1, var_num, glquadord, nsampleptperelem1d )
361
362 this%ks = ks; this%ke = ke
363 this%kall = ke - ks + 1
364
365 this%ls = ls; this%le = le
366 this%lall = le - ls + 1
367
368 select type(ptr_mesh2d => mesh2d)
369 class is (meshrectdom2d)
370 this%xmin_gl = ptr_mesh2d%xmin_gl
371 this%xmax_gl = ptr_mesh2d%xmax_gl
372 this%delx = ( this%xmax_gl - this%xmin_gl ) / real(ptr_mesh2d%NeGX, kind=rp)
373
374 this%ymin_gl = ptr_mesh2d%ymin_gl
375 this%ymax_gl = ptr_mesh2d%ymax_gl
376 this%dely = ( this%ymax_gl - this%ymin_gl ) / real(ptr_mesh2d%NeGY, kind=rp)
377
378 this%NeGX = ptr_mesh2d%NeGX
379 this%NeGY = ptr_mesh2d%NeGY
380 this%NprcX = ptr_mesh2d%NprcX
381 this%NprcY = ptr_mesh2d%NprcY
382 class default
383 log_info('MeshField_SpetralTransform2D_Init',*) 'Unexpected mesh type is given. Check!'
384 call prc_abort
385 end select
386
387 allocate( this%k(ks:ke) )
388 lx = this%xmax_gl - this%xmin_gl
389 do i=ks, ke
390 this%k(i) = i * 2.0_rp * pi / lx
391 end do
392
393 allocate( this%l(ls:le) )
394 ly = this%ymax_gl - this%ymin_gl
395 do j=ls, le
396 this%l(j) = j * 2.0_rp * pi / ly
397 end do
398
399 allocate( this%spectral_coef(ks:ke,ls:le,2,var_num) )
400
401 call elem_dummy%Init(elem%PolyOrder, .false.)
402
403 if ( this%NintGLpt > 0 ) then
404 allocate( this%IntIntrpMat(this%NintGLpt,elem%Nfp) )
405 allocate( this%IntXi(this%NintGLpt), this%IntWeight(this%NintGLpt) )
406
407 this%IntIntrpMat(:,:) = elem_dummy%GenIntGaussLegendreIntrpMat( glquadord, this%IntWeight, this%IntXi )
408 end if
409
410 if ( this%NsamplePtPerElem > 0 ) then
411 this%NsamplePtPerElem1D = nsampleptperelem1d
412 allocate( this%FFTIntrpMat(this%NsamplePtPerElem1D,elem%Nfp) )
413 allocate( this%FFT_Xi(this%NsamplePtPerElem1D) )
414
415 dx = 2.0_rp / real(this%NsamplePtPerElem1D,kind=rp)
416 do i=1, this%NsamplePtPerElem1D
417 this%FFT_Xi(i) = -1.0_rp + real(i - 0.5_rp,kind=rp) * dx
418 end do
419 this%FFTIntrpMat(:,:) = polynomial_genlagrangepoly( elem_dummy%PolyOrder, elem_dummy%x1, this%FFT_xi )
420
421 call this%fft_x%Init( this%NsamplePtPerElem1D * this%NeGX )
422 call this%fft_y%Init( this%NsamplePtPerElem1D * this%NeGY )
423 end if
424
425 call elem_dummy%Final()
426 return
427 end subroutine meshfield_spetraltransform2d_init
428
429!OCL SERIAL
430 subroutine meshfield_spetraltransform2d_final( this )
431 implicit none
432 class(meshfield_spetraltransform2d), intent(inout) :: this
433 !--------------------------------------------
434
435 call meshfield_spetraltransformbase_final( this )
436
437 if ( this%NsamplePtPerElem > 0 ) then
438 call this%fft_x%Final()
439 call this%fft_y%Final()
440 end if
441
442 deallocate( this%k, this%l, this%spectral_coef )
443 return
444 end subroutine meshfield_spetraltransform2d_final
445
446!OCL SERIAL
447 subroutine meshfield_spetraltransform2d_transform( this, q_list, mesh_num_x, mesh_num_y )
448 implicit none
449 class(meshfield_spetraltransform2d), intent(inout) :: this
450 integer, intent(in) :: mesh_num_x, mesh_num_y
451 type(meshfield2dlist), target :: q_list(this%var_num,mesh_num_x,mesh_num_y)
452
453 class(meshbase2d), pointer :: mesh2d
454 class(localmesh2d), pointer :: lmesh
455 !--------------------------------------------
456
457 mesh2d => q_list(1,1,1)%ptr%mesh
458 lmesh => mesh2d%lcmesh_list(1)
459
460 select case( this%eval_type_id )
462 call spectral_transform2d_dft( this%spectral_coef, &
463 q_list, this%var_num, mesh_num_x, mesh_num_y, & ! (in)
464 this%ks, this%ke, this%ls, this%le, lmesh%refElem2D%Nfp, lmesh%NeX, lmesh%NeY, & ! (in)
465 this%NeGY, this%NprcY, this%NsamplePtPerElem1D, & ! (in)
466 this%fft_x, this%fft_y, this%FFTIntrpMat )
468 call spectral_transform2d_l2projection( this%spectral_coef, & ! (out)
469 q_list, this%var_num, mesh_num_x*mesh_num_y, & ! (in)
470 this%ks, this%ke, this%ls, this%le, lmesh%refElem2D%Nfp, lmesh%NeX, lmesh%NeY, & ! (in)
471 this%IntIntrpMat, this%IntXi, this%IntWeight, this%NintGLPt, & ! (in)
472 this%xmin_gl, this%delx, this%xmax_gl - this%xmin_gl, & ! (in)
473 this%ymin_gl, this%dely, this%ymax_gl - this%ymin_gl ) ! (in)
474 end select
475
476 return
477 end subroutine meshfield_spetraltransform2d_transform
478
479!--- Private subroutines (1D)
480
481!OCL SERIAL
482 subroutine spectral_transform1d_dft( spectral_coef, &
483 q_list, var_num, mesh_num, ks, ke, Np, Ne, NsamplePerElem, &
484 fft, FFTIntrpMat, FFT_xi, &
485 xmin_gl, delx, Lx )
486
487 use mpi
488 use scale_prc, only: &
489 prc_local_comm_world
490 implicit none
491 integer, intent(in) :: ks, ke
492 integer, intent(in) :: np
493 integer, intent(in) :: ne
494 integer, intent(in) :: nsampleperelem
495 integer, intent(in) :: var_num
496 integer, intent(in) :: mesh_num
497 real(rp), intent(out) :: spectral_coef(ks:ke,2,var_num)
498 type(meshfield1dlist), target :: q_list(var_num,mesh_num)
499 class(fastfouriertransform1d), intent(in) :: fft
500 real(rp), intent(in) :: fftintrpmat(nsampleperelem,np)
501 real(rp), intent(in) :: fft_xi(nsampleperelem)
502 real(rp), intent(in) :: xmin_gl
503 real(rp), intent(in) :: delx
504 real(rp), intent(in) :: lx
505
506 real(rp) :: g_q(nsampleperelem,ne,mesh_num,var_num)
507 real(rp) :: q_tmp(np)
508 complex(RP) :: s_q(nsampleperelem*ne*mesh_num,var_num)
509
510 integer :: m
511 integer :: v
512 integer :: kel
513
514 integer :: nall
515 integer :: kk
516
517 real(rp) :: x_(nsampleperelem)
518 !-----------------------------------------------
519
520 !$omp parallel do collapse(3) private(v,m,kel,q_tmp, x_)
521 do v=1, var_num
522 do m=1, mesh_num
523 do kel=1, ne
524 q_tmp(:) = q_list(v,m)%ptr%local(1)%val(:,kel)
525 g_q(:,kel,m,v) = matmul( fftintrpmat, q_tmp )
526 end do
527 end do
528 end do
529
530 !$omp parallel do
531 do v=1, var_num
532 call fft%Forward_real( g_q(:,:,:,v), s_q(:,v) )
533 end do
534
535 nall = nsampleperelem * ne * mesh_num
536 !$omp parallel do private(kk)
537 do v=1, var_num
538 do kk=1, nall/2+1
539 spectral_coef(kk-1,1,v) = real(s_q(kk,v))
540 spectral_coef(kk-1,2,v) = aimag(s_q(kk,v))
541 end do
542 do kk=nall/2+1, nall
543 spectral_coef(kk-1-nall,1,v) = real(s_q(kk,v))
544 spectral_coef(kk-1-nall,2,v) = aimag(s_q(kk,v))
545 end do
546 end do
547 return
548 end subroutine spectral_transform1d_dft
549
550!OCL SERIAL
551 subroutine spectral_transform1d_l2projection( spectral_coef, &
552 q_list, var_num, mesh_num, ks, ke, Np, Ne, IntIntrpMat, IntXi, IntWeight, NintGLPt, &
553 xmin_gl, delx, Lx )
554
555 use mpi
556 use scale_prc, only: &
557 prc_local_comm_world
558 implicit none
559 integer, intent(in) :: ks, ke
560 integer, intent(in) :: np
561 integer, intent(in) :: ne
562 integer, intent(in) :: var_num
563 integer, intent(in) :: mesh_num
564 class(meshfield1dlist), target :: q_list(var_num,mesh_num)
565 real(rp), intent(out) :: spectral_coef(ks:ke,2,var_num)
566 integer, intent(in) :: nintglpt
567 real(rp), intent(in) :: intintrpmat(nintglpt,np)
568 real(rp), intent(in) :: intxi(nintglpt)
569 real(rp), intent(in) :: intweight(nintglpt)
570 real(rp), intent(in) :: xmin_gl
571 real(rp), intent(in) :: delx
572 real(rp), intent(in) :: lx
573
574 real(rp), allocatable :: s_coef_lc(:,:,:)
575 real(rp), allocatable :: s_coef(:,:,:)
576 real(rp), allocatable :: q_tmp(:,:,:)
577
578 integer :: vec_size
579 integer :: km
580
581 class(meshbase1d), pointer :: mesh1d
582 class(localmesh1d), pointer :: lmesh
583 integer :: ldom
584 integer :: meshid
585 type(localmeshfieldbaselist) :: lcfields(var_num)
586
587 integer :: kel, v
588 integer :: k, kk
589 integer :: ierr
590 !-----------------------------------------------
591
592 vec_size = var_num
593 km = ke
594
595 allocate( s_coef_lc(vec_size,2,0:km) )
596 allocate( s_coef(vec_size,2,0:km) )
597
598 !-
599 mesh1d => q_list(1,1)%ptr%mesh
600 lmesh => mesh1d%lcmesh_list(1)
601
602 !-
603
604 allocate( q_tmp(np,vec_size,ne) )
605
606 s_coef_lc(:,:,:) = 0.0_rp
607
608 do meshid=1, mesh_num
609 mesh1d => q_list(1,meshid)%ptr%mesh
610
611 do ldom=1, mesh1d%LOCAL_MESH_NUM
612 do v=1, var_num
613 lcfields(v)%ptr => q_list(v,meshid)%ptr%local(ldom)
614 end do
615 !$omp parallel do collapse(2)
616 do kel=lmesh%NeS, lmesh%NeE
617 do v=1, vec_size
618 q_tmp(:,v,kel) = lcfields(v)%ptr%val(:,kel)
619 end do
620 end do
621 call spectral_transform1d_l2projection_lc( s_coef_lc, &
622 q_tmp, 0, km, np, ne, vec_size, intintrpmat, intxi, intweight, nintglpt, &
623 (lmesh%xmin - xmin_gl)/lx-0.5_rp, delx/lx )
624 end do
625 end do
626
627 ! global sum
628 call mpi_allreduce( s_coef_lc, s_coef, vec_size * (km+1) * 2, &
629 mpi_double_precision, mpi_sum, prc_local_comm_world, ierr )
630
631 !-
632 !$omp parallel do private(kk)
633 do v=1, var_num
634 do k=ks, ke
635 kk = abs(k)
636 spectral_coef(k,1,v) = s_coef(v,1,kk)
637 spectral_coef(k,2,v) = s_coef(v,2,kk)
638 end do
639 end do
640
641 return
642 end subroutine spectral_transform1d_l2projection
643!OCL SERIAL
644 subroutine spectral_transform1d_l2projection_lc( spectral_coef, &
645 q, ks, ke, Np, Ne, vec_size, IntIntrpMat, IntXi, IntWeight, NintGLPt, &
646 xmin_lc, delx )
647 implicit none
648 integer, intent(in) :: ks, ke
649 integer, intent(in) :: np
650 integer, intent(in) :: ne
651 integer, intent(in) :: vec_size
652 real(rp), intent(in) :: q(np,vec_size,ne)
653 real(rp), intent(inout) :: spectral_coef(vec_size,2,ks:ke)
654 integer, intent(in) :: nintglpt
655 real(rp), intent(in) :: intintrpmat(nintglpt,np)
656 real(rp), intent(in) :: intxi(nintglpt)
657 real(rp), intent(in) :: intweight(nintglpt)
658 real(rp), intent(in) :: xmin_lc
659 real(rp), intent(in) :: delx
660
661 integer :: k
662 integer :: kel
663 integer :: v
664
665 real(rp) :: q_intrp(nintglpt,vec_size,ne)
666 real(rp) :: int_x(nintglpt,ne)
667
668 real(rp) :: phi(nintglpt)
669 real(rp) :: cos_kx(nintglpt)
670 real(rp) :: sin_kx(nintglpt)
671
672 real(rp) :: int_w(nintglpt)
673 !-------------------------------
674
675 int_w(:) = 0.5_rp * intweight(:) * delx
676
677 !$omp parallel private(kel,k,v,cos_kx,sin_kx,phi)
678 !$omp do
679 do kel=1, ne
680 int_x(:,kel) = 2.0_rp * pi * ( xmin_lc + delx * ( ( kel - 1.0_rp ) + 0.5_rp * ( 1.0_rp + intxi(:) ) ) )
681 q_intrp(:,:,kel) = matmul(intintrpmat, q(:,:,kel))
682 end do
683 !$omp do
684 do k=ks, ke
685 do kel=1, ne
686 phi(:) = mod( k * int_x(:,kel), 2.0_rp * pi )
687 cos_kx(:) = cos( phi )
688 sin_kx(:) = sin( phi )
689
690 do v=1, vec_size
691 spectral_coef(v,1,k) = spectral_coef(v,1,k) + sum(int_w(:) * cos_kx(:) * q_intrp(:,v,kel))
692 spectral_coef(v,2,k) = spectral_coef(v,2,k) - sum(int_w(:) * sin_kx(:) * q_intrp(:,v,kel))
693 end do
694 end do
695 end do
696 !$omp end parallel
697 return
698 end subroutine spectral_transform1d_l2projection_lc
699
700!--- Private subroutines (2D)
701
702!OCL SERIAL
703 subroutine spectral_transform2d_dft( spectral_coef, &
704 q_list, var_num, mesh_num_x, mesh_num_y, ks, ke, ls, le, Np1D, NeX, NeY, NeGY, NprcY, NsamplePerElem1D, &
705 fft_x, fft_y, FFTIntrpMat )
706
707 use mpi
708 use scale_prc, only: &
709 prc_local_comm_world
710 implicit none
711 integer, intent(in) :: ks, ke
712 integer, intent(in) :: ls, le
713 integer, intent(in) :: np1d
714 integer, intent(in) :: nex
715 integer, intent(in) :: ney, negy, nprcy
716 integer, intent(in) :: nsampleperelem1d
717 integer, intent(in) :: var_num
718 integer, intent(in) :: mesh_num_x
719 integer, intent(in) :: mesh_num_y
720 real(rp), intent(out) :: spectral_coef(ks:ke,ls:le,2,var_num)
721 class(meshfield2dlist), target :: q_list(var_num,mesh_num_x,mesh_num_y)
722 class(fastfouriertransform1d), intent(in) :: fft_x
723 class(fastfouriertransform1d), intent(in) :: fft_y
724 real(rp), intent(in) :: fftintrpmat(nsampleperelem1d,np1d)
725
726 real(rp) :: fftintrpmat_tr(np1d,nsampleperelem1d)
727
728 real(rp) :: g_q(nsampleperelem1d*nex*mesh_num_x,nsampleperelem1d*ney*mesh_num_y*var_num)
729 complex(RP) :: s_qx(nsampleperelem1d*nex*mesh_num_x,size(g_q,2))
730 complex(RP) :: g_qy(nsampleperelem1d*ney*mesh_num_y*nprcy,var_num,nsampleperelem1d*nex*mesh_num_x/nprcy)
731 complex(RP) :: s_q_lc(nsampleperelem1d*negy,var_num,nsampleperelem1d*nex*mesh_num_x/nprcy)
732 complex(RP) :: s_q(nsampleperelem1d*negy,var_num,nsampleperelem1d*nex*mesh_num_x)
733
734 integer :: v
735 integer :: xdim
736 integer :: prcy
737 integer :: j
738
739 integer :: nall_x, nall_y
740 integer :: kk, ll, kk_os
741
742 integer :: sendcount, recvcount
743 complex(RP) :: sendbuf(nsampleperelem1d*ney*mesh_num_y*var_num,nsampleperelem1d*nex*mesh_num_x)
744 complex(RP) :: recvbuf(nsampleperelem1d*ney*mesh_num_y,var_num,nsampleperelem1d*nex*mesh_num_x/nprcy,nprcy)
745 integer :: nx, local_nx
746 integer :: ny, local_ny
747 integer :: ierr
748 !-----------------------------------------------
749
750 !-
751 nall_x = nsampleperelem1d * nex * mesh_num_x
752 nall_y = nsampleperelem1d * negy
753
754 !-
755 fftintrpmat_tr(:,:) = transpose(fftintrpmat)
756 call spectral_transform2d_dft_sampling( g_q, &
757 q_list, var_num, mesh_num_x, mesh_num_y, np1d, nex, ney, nsampleperelem1d, &
758 fftintrpmat_tr )
759
760 !-
761 !$omp parallel do
762 do v=1, size(g_q,2)
763 call fft_x%Forward( g_q(:,v), s_qx(:,v) )
764 end do
765
766 !-
767 local_nx = nall_x
768 nx = local_nx
769
770 local_ny = nsampleperelem1d * ney * mesh_num_y * var_num
771 ny = nsampleperelem1d * negy * var_num
772
773 sendbuf(:,:) = transpose(s_qx)
774 sendcount = local_ny * (nx / nprcy)
775 recvcount = sendcount
776 call mpi_alltoall( sendbuf, sendcount, mpi_double_complex, &
777 recvbuf, recvcount, mpi_double_complex, prc_local_comm_world, ierr )
778
779 local_ny = nsampleperelem1d * ney * mesh_num_y
780 do v=1, var_num
781 do prcy=1, nprcy
782 do xdim=1, nsampleperelem1d*nex*mesh_num_x/nprcy
783 do j=1, local_ny
784 g_qy(j+(prcy-1)*local_ny,v,xdim) = recvbuf(j,v,xdim,prcy)
785 end do
786 end do
787 end do
788 end do
789
790 !-
791 !$omp parallel do collapse(2)
792 do v=1, var_num
793 do xdim=1, nx/nprcy
794 call fft_y%Forward( g_qy(:,v,xdim), s_q_lc(:,v,xdim) )
795 end do
796 end do
797
798 sendcount = size(s_q_lc)
799 recvcount = size(s_q_lc)
800 call mpi_allgather( s_q_lc, sendcount, mpi_double_complex, &
801 s_q, recvcount, mpi_double_complex, prc_local_comm_world, ierr )
802
803 !-
804 !$omp parallel do private(v,kk,ll)
805 do v=1, var_num
806 do ll=1, nall_y/2+1
807 do kk=1, nall_x/2+1
808 spectral_coef(kk-1,ll-1,1,v) = real(s_q(ll,v,kk))
809 spectral_coef(kk-1,ll-1,2,v) = aimag(s_q(ll,v,kk))
810 end do
811 do kk=nall_x/2+1, nall_x
812 spectral_coef(kk-1-nall_x,ll-1,1,v) = real(s_q(ll,v,kk))
813 spectral_coef(kk-1-nall_x,ll-1,2,v) = aimag(s_q(ll,v,kk))
814 end do
815 end do
816 do ll=nall_y/2+1, nall_y
817 do kk=1, nall_x/2+1
818 spectral_coef(kk-1,ll-1-nall_y,1,v) = real(s_q(ll,v,kk))
819 spectral_coef(kk-1,ll-1-nall_y,2,v) = aimag(s_q(ll,v,kk))
820 end do
821 do kk=nall_x/2+1, nall_x
822 spectral_coef(kk-1-nall_x,ll-1-nall_y,1,v) = real(s_q(ll,v,kk))
823 spectral_coef(kk-1-nall_x,ll-1-nall_y,2,v) = aimag(s_q(ll,v,kk))
824 end do
825 end do
826 end do
827 return
828 end subroutine spectral_transform2d_dft
829
830!OCL SERIAL
831 subroutine spectral_transform2d_dft_sampling( g_q, &
832 q_list, var_num, mesh_num_x, mesh_num_y, Np1D, NeX, NeY, NsamplePerElem1D, &
833 FFTIntrpMat_tr )
834
835 use mpi
836 use scale_prc, only: &
837 prc_local_comm_world
838 implicit none
839 integer, intent(in) :: np1d
840 integer, intent(in) :: nex, ney
841 integer, intent(in) :: nsampleperelem1d
842 integer, intent(in) :: var_num
843 integer, intent(in) :: mesh_num_x
844 integer, intent(in) :: mesh_num_y
845 real(rp), intent(out) :: g_q(nsampleperelem1d,nex,mesh_num_x,nsampleperelem1d,ney,mesh_num_y,var_num)
846 class(meshfield2dlist), intent(in) :: q_list(var_num,mesh_num_x,mesh_num_y)
847 real(rp), intent(in) :: fftintrpmat_tr(np1d,nsampleperelem1d)
848
849 real(rp) :: q_tmp(np1d,np1d)
850 real(rp) :: q_intrp1(nsampleperelem1d,np1d)
851 real(rp) :: q_intrp2(nsampleperelem1d,nsampleperelem1d)
852
853 integer :: mx, my, v
854 integer :: kel_x, kel_y, kel
855 integer :: p, p1, pp1, p2, pp2
856 !-----------------------------------------------
857
858 !$omp parallel do private(mx,my,v, kel_x,kel_y,kel, p,p1,pp1,p2,pp2, q_tmp,q_intrp1,q_intrp2) collapse(5)
859 do v=1, var_num
860 do my=1, mesh_num_y
861 do mx=1, mesh_num_x
862 do kel_y=1, ney
863 do kel_x=1, nex
864 kel = kel_x + (kel_y-1)*nex
865 do p2=1, np1d
866 do p1=1, np1d
867 p = p1 + (p2-1)*np1d
868 q_tmp(p1,p2) = q_list(v,mx,my)%ptr%local(1)%val(p,kel)
869 end do
870 end do
871
872 q_intrp1(:,:) = 0.0_rp
873 do p2=1, np1d
874 do p1=1, nsampleperelem1d
875 do pp1=1, np1d
876 q_intrp1(p1,p2) = q_intrp1(p1,p2) + fftintrpmat_tr(pp1,p1) * q_tmp(pp1,p2)
877 end do
878 end do
879 end do
880 q_intrp2(:,:) = 0.0_rp
881 do p2=1, nsampleperelem1d
882 do pp2=1, np1d
883 do p1=1, nsampleperelem1d
884 q_intrp2(p1,p2) = q_intrp2(p1,p2) + fftintrpmat_tr(pp2,p2) * q_intrp1(p1,pp2)
885 end do
886 end do
887 end do
888
889 do p2=1, nsampleperelem1d
890 g_q(:,kel_x,mx,p2,kel_y,my,v) = q_intrp2(:,p2)
891 end do
892 end do
893 end do
894 end do
895 end do
896 end do
897 return
898 end subroutine spectral_transform2d_dft_sampling
899
900!OCL SERIAL
901 subroutine spectral_transform2d_l2projection( spectral_coef, &
902 q_list, var_num, mesh_num, ks, ke, ls, le, Np1D, NeX, NeY, &
903 IntIntrpMat1D, IntXi1D, IntWeight1D, NintGLPt1D, &
904 xmin_gl, delx, Lx, ymin_gl, dely, Ly )
905
906 use mpi
907 use scale_prc, only: &
908 prc_local_comm_world
909 implicit none
910 integer, intent(in) :: ks, ke
911 integer, intent(in) :: ls, le
912 integer, intent(in) :: np1d
913 integer, intent(in) :: nex, ney
914 integer, intent(in) :: var_num
915 integer, intent(in) :: mesh_num
916 type(meshfield2dlist), target :: q_list(var_num,mesh_num)
917 real(rp), intent(out) :: spectral_coef(ks:ke,ls:le,2,var_num)
918 integer, intent(in) :: nintglpt1d
919 real(rp), intent(in) :: intintrpmat1d(nintglpt1d,np1d)
920 real(rp), intent(in) :: intxi1d(nintglpt1d)
921 real(rp), intent(in) :: intweight1d(nintglpt1d)
922 real(rp), intent(in) :: xmin_gl
923 real(rp), intent(in) :: delx
924 real(rp), intent(in) :: lx
925 real(rp), intent(in) :: ymin_gl
926 real(rp), intent(in) :: dely
927 real(rp), intent(in) :: ly
928
929 real(rp), allocatable :: s_coef_lc(:,:,:,:)
930 real(rp), allocatable :: s_coef(:,:,:,:)
931 real(rp), allocatable :: q_tmp(:,:,:)
932
933 real(rp) :: intintrpmat1d_tr(np1d,nintglpt1d)
934
935 integer :: vec_size
936 integer :: km
937
938 class(meshbase2d), pointer :: mesh2d
939 class(localmesh2d), pointer :: lmesh
940 integer :: ldom
941 integer :: meshid
942
943 integer :: kel, v
944 integer :: k, kk, l
945 integer :: ierr
946
947 type(localmeshfieldbaselist) :: lcfields(var_num)
948 !-----------------------------------------------
949
950 vec_size = var_num
951 km = ke
952
953 allocate( s_coef_lc(vec_size,2,0:km,ls:le) )
954 allocate( s_coef(vec_size,2,0:km,ls:le) )
955
956 !-
957 mesh2d => q_list(1,1)%ptr%mesh
958 lmesh => mesh2d%lcmesh_list(1)
959
960 intintrpmat1d_tr(:,:) = transpose(intintrpmat1d)
961 !-
962
963 allocate( q_tmp(np1d**2,vec_size,nex*ney) )
964
965 s_coef_lc(:,:,:,:) = 0.0_rp
966
967 do meshid=1, mesh_num
968 mesh2d => q_list(1,meshid)%ptr%mesh
969 do ldom=1, mesh2d%LOCAL_MESH_NUM
970 lmesh => mesh2d%lcmesh_list(ldom)
971
972 do v=1, var_num
973 lcfields(v)%ptr => q_list(v,meshid)%ptr%local(ldom)
974 end do
975 !$omp parallel do collapse(2)
976 do kel=lmesh%NeS, lmesh%NeE
977 do v=1, vec_size
978 q_tmp(:,v,kel) = lcfields(v)%ptr%val(:,kel)
979 end do
980 end do
981 call spectral_transform2d_l2projection_lc( s_coef_lc, &
982 q_tmp, 0, km, ls, le, np1d, nex, ney, vec_size, &
983 intintrpmat1d_tr, intxi1d, intweight1d, nintglpt1d, &
984 (lmesh%xmin - xmin_gl)/lx-0.5_rp, delx/lx, &
985 (lmesh%ymin - ymin_gl)/ly-0.5_rp, dely/ly )
986 end do
987 end do
988
989 ! global sum
990 call mpi_allreduce( s_coef_lc, s_coef, vec_size * (km+1)*(le-ls+1) * 2, &
991 mpi_double_precision, mpi_sum, prc_local_comm_world, ierr )
992
993 !-
994 !$omp parallel do collapse(2) private(kk)
995 do v=1, var_num
996 do l=ls, le
997 do k=ks, ke
998 kk = abs(k)
999 if ( k >= 0 ) then
1000 spectral_coef(k,l,1,v) = s_coef(v,1,kk,l)
1001 spectral_coef(k,l,2,v) = s_coef(v,2,kk,l)
1002 else
1003 spectral_coef(k,l,1,v) = s_coef(v,1,kk,-l)
1004 spectral_coef(k,l,2,v) = - s_coef(v,2,kk,-l)
1005 end if
1006 end do
1007 end do
1008 end do
1009
1010 return
1011 end subroutine spectral_transform2d_l2projection
1012!OCL SERIAL
1013 subroutine spectral_transform2d_l2projection_lc( spectral_coef, &
1014 q, ks, ke, ls, le, Np1D, NeX, NeY, vec_size, IntIntrpMat1D_tr, IntXi1D, IntWeight1D, NintGLpt1D, &
1015 xmin_lc, delx, ymin_lc, dely )
1016 implicit none
1017 integer, intent(in) :: ks, ke
1018 integer, intent(in) :: ls, le
1019 integer, intent(in) :: np1d
1020 integer, intent(in) :: nex
1021 integer, intent(in) :: ney
1022 integer, intent(in) :: vec_size
1023 real(rp), intent(in) :: q(np1d,np1d,vec_size,nex,ney)
1024 real(rp), intent(inout) :: spectral_coef(vec_size,2,ks:ke,ls:le)
1025 integer, intent(in) :: nintglpt1d
1026 real(rp), intent(in) :: intintrpmat1d_tr(np1d,nintglpt1d)
1027 real(rp), intent(in) :: intxi1d(nintglpt1d)
1028 real(rp), intent(in) :: intweight1d(nintglpt1d)
1029 real(rp), intent(in) :: xmin_lc
1030 real(rp), intent(in) :: delx
1031 real(rp), intent(in) :: ymin_lc
1032 real(rp), intent(in) :: dely
1033
1034 integer :: k, l
1035 integer :: kel_x, kel_y
1036 integer :: p, px, py
1037 integer :: v
1038
1039 real(rp) :: q_intrp_tmp(nintglpt1d,np1d,vec_size)
1040 real(rp) :: q_intrp_tmp2(nintglpt1d**2,vec_size)
1041 real(rp) :: q_intrp(nintglpt1d**2,vec_size,nex,ney)
1042 real(rp) :: int_x(nintglpt1d,nex)
1043 real(rp) :: int_y(nintglpt1d,ney)
1044
1045 real(rp) :: phi(nintglpt1d**2)
1046 real(rp) :: cos_phi(nintglpt1d**2)
1047 real(rp) :: sin_phi(nintglpt1d**2)
1048
1049 real(rp) :: int_w(nintglpt1d**2)
1050 !-------------------------------
1051
1052 !$omp parallel private(kel_x,kel_y,k,l,v,p,px,py,cos_phi,sin_phi,phi,q_intrp_tmp,q_intrp_tmp2)
1053 !$omp do
1054 do py=1, nintglpt1d
1055 do px=1, nintglpt1d
1056 p = px + (py-1)*nintglpt1d
1057 int_w(p) = 0.25_rp * delx * dely * intweight1d(px) * intweight1d(py)
1058 end do
1059 end do
1060 !$omp do
1061 do kel_x=1, nex
1062 int_x(:,kel_x) = 2.0_rp * pi * ( xmin_lc + delx * ( ( kel_x - 1.0_rp ) + 0.5_rp * ( 1.0_rp + intxi1d(:) ) ) )
1063 end do
1064 !$omp do
1065 do kel_y=1, ney
1066 int_y(:,kel_y) = 2.0_rp * pi * ( ymin_lc + dely * ( ( kel_y - 1.0_rp ) + 0.5_rp * ( 1.0_rp + intxi1d(:) ) ) )
1067 end do
1068 !$omp do collapse(2)
1069 do kel_y=1, ney
1070 do kel_x=1, nex
1071 q_intrp_tmp(:,:,:) = 0.0_rp
1072 do v=1, vec_size
1073 do py=1, np1d
1074 do px=1, nintglpt1d
1075 q_intrp_tmp(px,py,v) = q_intrp_tmp(px,py,v) &
1076 + sum(intintrpmat1d_tr(:,px) * q(:,py,v,kel_x,kel_y))
1077 end do
1078 end do
1079 end do
1080
1081 q_intrp_tmp2(:,:) = 0.0_rp
1082 do py=1, nintglpt1d
1083 do v=1, vec_size
1084 do px=1, nintglpt1d
1085 p = px + (py-1)*nintglpt1d
1086 q_intrp_tmp2(p,v) = q_intrp_tmp2(p,v) &
1087 + sum(intintrpmat1d_tr(:,py) * q_intrp_tmp(px,:,v))
1088 end do
1089 end do
1090 end do
1091 q_intrp(:,:,kel_x,kel_y) = q_intrp_tmp2(:,:)
1092 end do
1093 end do
1094 !$omp do collapse(2)
1095 do l=ls, le
1096 do k=ks, ke
1097 do kel_y=1, ney
1098 do kel_x=1, nex
1099 do py=1, nintglpt1d
1100 do px=1, nintglpt1d
1101 p = px + (py-1)*nintglpt1d
1102 phi(p) = mod( k * int_x(px,kel_x) + l * int_y(py,kel_y), 2.0_rp * pi )
1103 end do
1104 end do
1105 cos_phi(:) = cos( phi(:) )
1106 sin_phi(:) = sin( phi(:) )
1107
1108 do v=1, vec_size
1109 spectral_coef(v,1,k,l) = spectral_coef(v,1,k,l) + sum(int_w(:) * cos_phi(:) * q_intrp(:,v,kel_x,kel_y))
1110 spectral_coef(v,2,k,l) = spectral_coef(v,2,k,l) - sum(int_w(:) * sin_phi(:) * q_intrp(:,v,kel_x,kel_y))
1111 end do
1112 end do
1113 end do
1114 end do
1115 end do
1116 !$omp end parallel
1117 return
1118 end subroutine spectral_transform2d_l2projection_lc
1119
module FElib / Element / Base
module FElib / Element / line
module FElib / Mesh / Local 1D
module FElib / Mesh / Local 2D
module FElib / Mesh / Local 3D
module FElib / Mesh / Base 1D
module FElib / Mesh / Base 2D
module FElib / Mesh / Rectangle 2D domain
module FElib / Data / base
Module common / Polynomial.
real(rp) function, dimension(size(x), nord+1), public polynomial_genlagrangepoly(nord, x_lgl, x)
A function to obtain the Lagrange basis functions related to the Gauss-Legendre-Lobatto (GLL) points.
Derived type representing a 1D reference element.
Derived type representing a 2D reference element.
Derived type representing a 3D reference element.
Derived type representing a line element.
Derived type representing a local mesh for 1D domain.
Derived type representing a local mesh for 2D domain.
Derived type to manage a local 3D computational domain.
Derived type representing a field with 1D local mesh.
Derived type to manage a computational mesh (base type for 1D domain)
Derived type to manage a computational mesh (base type for 2D domain)
Derived type to manage a rectangular 2D computational domain.
Derived type representing a field with 1D mesh.
Derived type representing a field with 2D mesh.