source: trunk/00FlowSolve_PL/PROJECTS/NEW_SRC/filter4.f90 @ 4

Last change on this file since 4 was 4, checked in by xlvlod, 18 years ago

import initial des vraies codes.

File size: 14.5 KB
Line 
1subroutine filter
2#define DEBUG_LEVEL 1
3 use mpi_parameters
4 use boundary_information
5 use dependent_variables
6 use counters_flags_etc
7 implicit none
8
9 integer                               :: sizeofreal,locnx
10 include '../input/problem_size.h'
11 include 'mpif.h'
12
13! At designated time steps, apply fourth order compact spatial filters
14if( mod(istep,i_filter) == 0  .and. istep .ne. 0 ) then
15
16#if DEBUG_LEVEL >= 1
17 if(myid==0) write(0,*) 'hello world from subroutine filter '
18#endif
19
20 if( boundary_type2(1,1)=='periodic' .and. boundary_type4(1,1)=='periodic' ) then
21   locnx = (nx-1)/nprocs
22  else
23   locnx = nx/nprocs
24  endif
25
26!!  create a derived data type
27  call MPI_TYPE_EXTENT(MPI_REAL,sizeofreal,ierr)
28  call MPI_TYPE_VECTOR(locnx,1,1,MPI_REAL,oneslice,ierr)
29  call MPI_TYPE_HVECTOR(ny,1,nx*sizeofreal,oneslice,twoslice,ierr)
30  call MPI_TYPE_HVECTOR(locnz,1,nx*ny*sizeofreal,twoslice,subslice,ierr)
31  call MPI_TYPE_COMMIT(subslice,ierr)
32  call MPI_BARRIER(comm,ierr)
33
34  call filter4(U)
35  call filter4(v)
36  call filter4(W)
37  call filter4(s1)
38  call filter4(s2)
39
40  call MPI_BARRIER(comm,ierr)
41
42!! free data type
43  call MPI_TYPE_FREE(oneslice,ierr)
44  call MPI_TYPE_FREE(twoslice,ierr)
45  call MPI_TYPE_FREE(subslice,ierr)
46
47endif
48
49end subroutine filter
50
51subroutine filter4(U)
52#define DEBUG_LEVEL 1
53 use mpi_parameters
54 use boundary_information
55 use columnslab
56
57 implicit none
58 include 'mpif.h'
59
60 include '../input/problem_size.h'
61 integer                               :: n1,n2,n3,nzderiv,locnx
62 real, dimension(:,:,:), allocatable   :: block_of_cols
63 real, dimension(nx,ny,locnz)          :: U
64
65 if( boundary_type2(1,1)=='periodic' .and. boundary_type4(1,1)=='periodic' ) then
66   locnx = (nx-1)/nprocs
67  else
68   locnx = nx/nprocs
69  endif
70
71! filter in x and y directions, overwriting input array in both cases
72 call filter_x4(U,U,nx,ny,locnz)
73 call filter_y4(U,U,nx,ny,locnz)
74
75!filter in z direction :
76!*******************************************************
77! See compact_ddz_mpi for more details, but basically, each processor
78! needs to ship sub-blocks of its own dataslice and recieve those
79! necessary to construct a block with dimensions nx/numprocs * ny * nz.
80! Filtering is done on these blocks and the results shipped back
81! to the appropriate locations
82!*******************************************************
83
84 nzderiv=nz   ! don't use nzderiv < nz logic
85!Both CASE1 and CASE2 require simple calls to compact_ddz
86 if( numprocs == 1 .and. locnz == nz .and. nzderiv == nz ) then
87  goto 999   ! CASE1
88 elseif(numprocs > 1 .and. nzderiv == locnz .and. locnz < nz) then
89  goto 999   ! CASE2
90 elseif(numprocs > 1 .and. nzderiv == nz .and. nz > locnz) then
91!CASE3 logic
92 
93  allocate ( block_of_cols( locnx,ny,numprocs*locnz) )
94
95!!*******************************************************************************
96!!*************   DO THE DATA EXCHANGES  ****************************************
97!!*******************************************************************************
98
99!!(1) Ship portions of my slice needed by other processes and
100!!    receive data needed to fill in "block_of_cols"
101
102   call slabs_to_columns(U,block_of_cols)
103
104!!(2) Apply z4 filtering to "block_of_cols"
105
106   n1=locnx
107   n2=ny
108   n3=locnz*numprocs
109   call filter_z4(block_of_cols,block_of_cols,n1,n2,n3)
110
111!!(3) Send filtered fields to other processes
112!!    and receive their results.
113
114   call columns_to_slabs(block_of_cols,U)
115   
116!!*******************************************************************************
117!!*************    END DATA EXCHANGES    ****************************************
118!!*******************************************************************************
119
120  if( boundary_type2(1,1)=='periodic' .and. boundary_type4(1,1)=='periodic' ) then
121   U(nx,:,:)=U(1,:,:)  ! we didn't compute the values at extra bdry point location in x
122  endif
123
124  deallocate(block_of_cols)
125  return
126 endif
127
128999 continue   ! CASE1 & CASE2
129 n1=nx
130 n2=ny
131 n3=nzderiv
132 call filter_z4(U,U,n1,n2,n3)
133
134end subroutine filter4
135
136!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137subroutine filter_x4(data,deriv,nx,ny,nz)
138! routine to perform 4th order filtering wrt x (1st dimension)
139! of a 3d field stored in data(1:nx,1:ny,1:nz).
140!
141! inputs
142!        data       nx,ny,nz array of input values
143!        nx,ny,nz   dimensions of field to be differentiated
144!
145! output
146!        deriv      nx,ny,nz array containing the 4th order
147!                   filtered (in x) field
148!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
149
150 use grid_info
151 use boundary_information
152use user_parameters,        only: LAPACK_FLAG
153 implicit none
154
155!!! double precision, dimension(:,:),allocatable    :: work
156 real, dimension(:,:),allocatable    :: work
157 integer                             :: i,j,k,nx,ny,nz,ierr
158 real                                :: data(nx,ny,nz),deriv(nx,ny,nz)
159!!! double precision                    :: a,b,c
160 real                    :: a,b,c
161
162 real,allocatable,dimension(:)       :: kx,SF,in,out,tmp
163 real                                :: pi,kx_max,xnorm,kstar,dk
164 integer*8                           :: plan_f,plan_i     !size must match pointer size, 8 for DEC alphas
165 integer                             :: N
166 include 'fftw_kw.inc'               !  predefined FFTW constants
167
168
169 if( boundary_type2(1,1)=='periodic' ) then
170  N=nx-1                 ! nx includes both boundary points, N only 1
171  allocate(kx(N+1),SF(N))
172  allocate( in(N),out(N),tmp(N) )
173
174! X preliminaries, setup fftw "plan"
175  call rfftw_f77_create_plan(plan_f,N,FFTW_REAL_TO_COMPLEX,FFTW_ESTIMATE)
176  call rfftw_f77_create_plan(plan_i,N,FFTW_COMPLEX_TO_REAL,FFTW_ESTIMATE)
177
178
179! create the x array, align with the data arrays
180  pi=4.*atan(1.)
181  xnorm = 1./float(N)    ! only normalize in wavenumber space here
182  do i=1,N/2+1
183   kx(i)=2.*pi*(i-1.)    ! FFTW real to half-complex storage
184  enddo
185  do i=2,N/2
186   kx(N-i+2)=kx(i)       ! FFTW real to half-complex storage
187  enddo
188  kx(N+1)=0.             ! extra location, convenient for alignment of arrays
189
190! define smoothing filter
191  kx_max=kx(N/2+1)
192  kstar=(8./9.)*kx_max 
193  do i=1,N
194       !if( kx(i) >= (8./9.)*kx_max ) then
195       ! SF(i)=0.
196       !else
197       ! SF(i)=1.0
198       !endif
199   SF(i)=0.5*( -tanh( 8.*(kx(i)-kstar)/(kx_max) ) + 1. )
200  enddo
201
202  do k=1,nz
203   do j=1,ny
204
205! x transforms; filter & inverse transform
206    in(1:N)=data(1:N,j,k)
207    call rfftw_f77_one(plan_f,in,out)
208    tmp(1:N)=SF(1:N)*out(1:N)*xnorm
209    call rfftw_f77_one(plan_i,tmp,out)
210    deriv(1:N,j,k)=out
211    deriv(nx,j,k)=deriv(1,j,k)
212
213   enddo
214  enddo
215
216  call rfftw_f77_destroy_plan(plan_f)
217  call rfftw_f77_destroy_plan(plan_i)
218  deallocate( kx,SF,in,out,tmp )
219  return
220 endif
221
222!               GENERAL, NONPERIODIC LOGIC
223allocate ( work(nx,ny) )
224!Set filter coefficients:
225 a=(5.+6.*alpha)/8.
226 b=(1.+2.*alpha)/2.
227 c=-(1.-2.*alpha)/8.
228
229!Loop through each horizontal plane
230 do k=1,nz
231
232!Create rhs vectors, store in work(:,:,1)
233  do i=3,nx-2
234   do j=1,ny
235    work(i,j)=a*data(i,j,k) + b*( data(i+1,j,k)+data(i-1,j,k) )/2.   &
236               + c*( data(i+2,j,k)+data(i-2,j,k) )/2.
237   enddo
238  enddo
239
240  do j=1,ny
241   work(1,j)= (15./16.)*data(1,j,k) + (1./16.)*( 4*data(2,j,k)         &
242               -6.*data(3,j,k) + 4.*data(4,j,k) - data(5,j,k) )
243   work(2,j)= (3./4.)*data(2,j,k) + (1./16.)*( data(1,j,k)             &
244               +6.*data(3,j,k) - 4.*data(4,j,k) + data(5,j,k) )
245
246   work(nx,j)=(15./16.)*data(nx,j,k) + (1./16.)*( 4*data(nx-1,j,k)     &
247               -6.*data(nx-2,j,k) + 4.*data(nx-3,j,k) - data(nx-4,j,k))
248   work(nx-1,j)= (3./4.)*data(nx-1,j,k) + (1./16)*( data(nx,j,k)      &
249               +6.*data(nx-2,j,k) - 4.*data(nx-3,j,k) + data(nx-4,j,k))
250  enddo
251
252! compute the filtered fields for plane k, results overwritten onto work(:,:)
253 if( LAPACK_FLAG == 'double' ) then
254!!!  call DGBTRS('N',nx,1,1,ny,Grid(0)%filt_x,4,Grid(0)%piv_fx,work(1,1),nx,ierr)
255      write(0,*) 'LAPACK_FLAG = double instead of single'
256      stop
257 elseif( LAPACK_FLAG == 'single' ) then
258  call SGBTRS('N',nx,1,1,ny,Grid(0)%filt_x,4,Grid(0)%piv_fx,work(1,1),nx,ierr)
259 endif
260 
261  deriv(:,:,k)=work(:,:)     !store the results in deriv(:,:,k)
262
263 enddo ! next k plane
264
265 deallocate ( work )
266end subroutine filter_x4
267
268subroutine filter_y4(data,deriv,nx,ny,nz)
269! routine to perform 4th order filtering wrt y (2nd dimension)
270! of a 3d field stored in data(1:nx,1:ny,1:nz).
271!
272! inputs
273!        data       nx,ny,nz array of input values
274!        nx,ny,nz   dimensions of field to be differentiated
275
276! output
277!        deriv      nx,ny,nz array containing the 4th order
278!                   accurate filtered (in y ) field
279!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
280
281 use grid_info
282 use boundary_information
283use user_parameters,        only: LAPACK_FLAG
284 implicit none
285
286!!! double precision, dimension(:,:),allocatable    :: work
287 real, dimension(:,:),allocatable    :: work
288 integer                             :: i,j,k,nx,ny,nz,ierr
289 real                                :: data(nx,ny,nz),deriv(nx,ny,nz)
290!!! double precision                    :: a,b,c
291 real                    :: a,b,c
292
293 real,allocatable,dimension(:)       :: ky,SF,in,out,tmp
294 real                                :: pi,ky_max,xnorm,kstar,dk
295 integer*8                           :: plan_f,plan_i     !size must match pointer size, 8 for DEC alphas
296 integer                             :: N
297 include 'fftw_kw.inc'               !  predefined FFTW constants
298
299
300 if( boundary_type4(1,1)=='periodic' ) then
301  N=ny-1                 ! ny includes both boundary points, N only 1
302  allocate( in(N),out(N),tmp(N) )
303  allocate(ky(N+1),SF(N))
304
305! Y preliminaries, setup fftw "plan"
306  call rfftw_f77_create_plan(plan_f,N,FFTW_REAL_TO_COMPLEX,FFTW_ESTIMATE)
307  call rfftw_f77_create_plan(plan_i,N,FFTW_COMPLEX_TO_REAL,FFTW_ESTIMATE)
308
309! create the y array, align with the data arrays
310  pi=4.*atan(1.)
311  xnorm = 1./float(N)    ! only normalize in wavenumber space here
312  do j=1,N/2+1
313   ky(j)=2.*pi*(j-1.)    ! FFTW real to half-complex storage
314  enddo
315  do j=2,N/2
316   ky(N-j+2)=ky(j)       ! FFTW real to half-complex storage
317  enddo
318  ky(N+1)=0.             ! extra location, convenient for alignment of arrays
319
320! define smoothing filter
321  ky_max=ky(N/2+1)
322  kstar=(8./9.)*ky_max
323
324  if( N <= 16 ) then
325   do j=1,N
326     SF(j)=1.0    ! no filtering
327   enddo
328  elseif( N > 16 ) then
329   do j=1,N
330    SF(j)=0.5*( -tanh( 8.*(ky(j)-kstar)/(ky_max) ) + 1. )
331   enddo
332  endif
333
334  do k=1,nz
335   do i=2,nx-1
336
337! y transforms; filter & inverse transform
338    in(1:N)=data(i,1:N,k)
339    call rfftw_f77_one(plan_f,in,out)
340    tmp(1:N)=SF(1:N)*out(1:N)*xnorm
341    call rfftw_f77_one(plan_i,tmp,out)
342    deriv(i,1:N,k)=out
343    deriv(i,ny,k)=deriv(i,1,k)
344
345   enddo
346  enddo
347  deriv(1,:,:)=data(1,:,:)
348  deriv(nx,:,:)=data(nx,:,:)
349
350  call rfftw_f77_destroy_plan(plan_f)
351  call rfftw_f77_destroy_plan(plan_i)
352  deallocate( ky,SF,in,out,tmp )
353  return
354 endif
355
356!               GENERAL, NONPERIODIC LOGIC
357
358 allocate ( work(ny,nx) )
359 a=(5.+6.*alpha)/8.
360 b=(1.+2.*alpha)/2.
361 c=-(1.-2.*alpha)/8.
362
363!Loop through each horizontal plane
364 do k=1,nz
365! create rhs vectors, store in work(:,:,1)
366  do j=3,ny-2
367   do i=1,nx
368    work(j,i)=a*data(i,j,k) + b*( data(i,j+1,k)+data(i,j-1,k) )/2. &
369               + c*( data(i,j+2,k)+data(i,j-2,k) )/2.
370   enddo
371  enddo
372
373  do i=1,nx
374   work(1,i)= (15./16.)*data(i,1,k) + (1./16.)*( 4.*data(i,2,k)          &
375              -6.*data(i,3,k) + 4.*data(i,4,k) - data(i,5,k) )
376   work(2,i)= (3./4.)*data(i,2,k) + (1./16.)*( data(i,1,k)              &
377              +6.*data(i,3,k) - 4.*data(i,4,k) + data(i,5,k) )
378
379   work(ny,i)=(15./16.)*data(i,ny,k) + (1./16.)*( 4.*data(i,ny-1,k)      &
380               -6.*data(i,ny-2,k) + 4.*data(i,ny-3,k) - data(i,ny-4,k))
381   work(ny-1,i)=(3./4.)*data(i,ny-1,k) + (1./16)*( data(i,ny,k)        &
382                 +6.*data(i,ny-2,k) - 4.*data(i,ny-3,k) + data(i,ny-4,k))
383  enddo
384
385! compute the filtered fields for plane k, overwriting results into work(:,:)
386 if( LAPACK_FLAG == 'double' ) then
387!!!  call DGBTRS('N',ny,1,1,nx,Grid(0)%filt_y,4,Grid(0)%piv_fy,work(1,1),ny,ierr)
388      write(0,*) 'LAPACK_FLAG = double instead of single'
389      stop
390 elseif( LAPACK_FLAG == 'single' ) then
391  call SGBTRS('N',ny,1,1,nx,Grid(0)%filt_y,4,Grid(0)%piv_fy,work(1,1),ny,ierr)
392 endif
393
394!     store the results in deriv(:,:,k)
395  do i=1,nx
396   do j=1,ny
397    deriv(i,j,k)=work(j,i)
398   enddo
399  enddo
400
401 enddo   ! next k plane
402
403 deallocate ( work )
404end subroutine filter_y4
405
406subroutine filter_z4(data,deriv,nx,ny,nz)
407!
408!       routine to perform 4th order filtering wrt z (3rd dimension)
409!       of a 3d field stored in data(1:nx,1:ny,1:nz).
410!
411! inputs
412!        data       nx,ny,nz array of input values
413!        nx,ny,nz   dimensions of field to be filtered
414!
415! output
416!        deriv      nx,ny,nz array containing the filtered field
417!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
418
419 use grid_info
420 use user_parameters, only: LAPACK_FLAG
421 implicit none
422
423!!! double precision, dimension(:,:),allocatable    :: work
424 real, dimension(:,:),allocatable    :: work
425 integer                             :: i,j,k,nx,ny,nz,ierr
426 real                                :: data(nx,ny,nz),deriv(nx,ny,nz)
427!!! double precision                    :: a,b,c
428 real                    :: a,b,c
429 allocate ( work(nz,nx) )
430     
431 a=(5.+6.*alpha)/8.
432 b=(1.+2.*alpha)/2.
433 c=-(1.-2.*alpha)/8.
434
435!Loop through each xz vertical plane
436 do j=1,ny
437! create rhs vectors, store in work(:,:,1)
438
439  do k=3,nz-2
440   do i=1,nx
441    work(k,i)=a*data(i,j,k) + b*( data(i,j,k+1)+data(i,j,k-1) )/2.   &
442               + c*( data(i,j,k+2)+data(i,j,k-2) )/2.
443   enddo
444  enddo
445
446  do i=1,nx
447   work(1,i)= (15./16.)*data(i,j,1) + (1./16.)*( 4.*data(i,j,2)             &
448              -6.*data(i,j,3) + 4.*data(i,j,4) - data(i,j,5) )
449   work(2,i)= (3./4.)*data(i,j,2) + (1./16.)*( data(i,j,1)                 &
450              +6.*data(i,j,3) - 4.*data(i,j,4) + data(i,j,5) )
451
452   work(nz,i)=(15./16.)*data(i,j,nz) + (1./16.)*( 4.*data(i,j,nz-1)         &
453               -6.*data(i,j,nz-2) + 4.*data(i,j,nz-3) - data(i,j,nz-4))
454   work(nz-1,i)=(3./4.)*data(i,j,nz-1) + (1./16.)*( data(i,j,nz)           &
455                 +6.*data(i,j,nz-2) - 4.*data(i,j,nz-3) + data(i,j,nz-4))
456  enddo
457
458!Filter the fields wrt z for plane j, overwriting results into work(:,:)
459 if( LAPACK_FLAG == 'double' ) then
460!!!  call DGBTRS('N',nz,1,1,nx,Grid(0)%filt_z,4,Grid(0)%piv_fz,work(1,1),nz,ierr)
461      write(0,*) 'LAPACK_FLAG = double instead of single'
462      stop
463 elseif( LAPACK_FLAG == 'single' ) then
464  call SGBTRS('N',nz,1,1,nx,Grid(0)%filt_z,4,Grid(0)%piv_fz,work(1,1),nz,ierr)
465 endif
466
467!Store the results in deriv(:,j,:)
468  do k=1,nz
469   do i=1,nx
470    deriv(i,j,k)=work(k,i)
471   enddo
472  enddo
473
474 enddo    ! go on to the next plane
475
476 deallocate ( work )
477end subroutine filter_z4
478
Note: See TracBrowser for help on using the repository browser.