source: trunk/SpectralModelF90/PROJECTS/trivial/transform3d.f @ 6

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

import initial from SVN_BASE_TRUNK

File size: 29.4 KB
Line 
1c*********************************************************************************
2c*********************************************************************************
3c
4c   This file contains the subroutines transform3d, five, six and seven
5c   These routines must be linked to the Temperton FFT package to run
6c
7c*******************************************************************************
8c*******************************************************************************
9c     Modified to operate on physical space data distributed in
10c     horizontal "slabs" across processors and wavenumber space
11c     data distributed in columns, i.e. each processor stores a
12c     finite z range of P. space data and a finite kx range of
13c     wavenumber space data. 2 data swapping routines perform the
14c     interprocessor exchanges: slabs_to_columns and columns_to_slabs.
15c     Except for the number of transforms executed as a block, these
16c     transform routines are applied as usual.
17
18c     Each processor performs the following operations on a portion
19c     of the globally distributed data:
20
21c     Forward Transforms:  real data arranged in "slabs"
22c      FFT in x, FFT in y, swap data and construct column, S/C transform in z
23c     Inverse Transforms:  complex data arranged in "columns"
24c      IC/S transform in z, swap data and construct slab, IFFT in y, IFFT in x
25c*****************************************************************************
26
27      subroutine transform3d (x, x_cplx, nx, ny, nz, iswitch, tswitch, itrig,
28     *                       trigx, trigy, trigz, wn, ifax, ifay, ifaz,
29     *                       num_dims,work,scratch,xt,myid,numprocs,locnx,locnz,
30     *                       comm,twoslice,subslice)
31
32C---------------------------------------------------------------------
33C
34C   transform3d.f - This FORTRAN subroutine accepts data
35c                   stored in a 3-dimensional array and performs
36c                   one of the the following transforms:
37c
38c           iswitch=1 
39c           transform real data to the complex frequency domain
40c           Fourier transforms are applied in the x and y directions
41c           sine or cosine transforms are applied in the z direction
42c           tswitch='s' for sine transform, 'c' for cosine
43c
44c           iswitch=-1 
45c           transform complex frequency domain data to real physical space data
46c           Inverse Fourier transforms are applied in the x and y directions
47c           sine or cosine transforms are applied in the z direction
48c           N.B. sine/cosine transforms are thei own inverses
49c           tswitch='s' for sine transform, 'c' for cosine 
50c
51c           This subroutine makes use of the Temperton FFT package
52c           cfft99.f along with the subroutines five.f, six.f and
53c           seven.f 
54c
55c           when num_dims=3, the minimum values for nx,ny and nz are(8,8,8)
56c           when num_dims=2, the minimum values for nx,ny and nz are(8,1,8)
57c           and ny=0 so that nyp1=ny+1=1
58
59c
60c   code written by Kraig Winters  June 30, 1997
61c   this is a modified version of the Bryan Johns/KW code
62c   extended to allow the cases FFS/FFC/FFF in 2 or 3 dimensions
63c   extended for MPI parallel execution KW 8/18/00
64c
65
66c
67c   inputs:
68c
69c   nx,ny,nz   integers defining (base) array sizes
70c   num_dims   integer specifying 2 (x-z) or 3 (xyz) dimensional problem (z="up")
71c   x          real array of size (nx+2,ny+1,nz+1)          for iswitch=1 or
72c              complex array of size (nx/2+1,ny+1,nz+1)     for iswitch=-1
73c              by convention first index ==> x direction, second ==> y, third ==> z
74c   iswitch    integer specifying transform direction     +1==> forward transform
75c   tswitch    character*1 specifying symmetry of z transform 'c'/'s'/'f'
76c              for cosine/sine/fourier transforms in the vertical direction
77c   itrig      integer flag specifying whether trig setup calculations need to be
78c              done. itrig=1 specifies tables need to be computed.
79c              N.B. if itrig=1, tables will be computed and then itrig set to 0.
80c
81c   The following arrays must be dimensioned and passed but values are
82c   determined within transform3d.f when itrig=1. These arrays should not be
83c   overwritten if subsequent calls with itrig=0 are made to transform3d.f.
84c
85c  trigx  real array of size 3*(nx+2)/2+1  contains trig tables for x transforms
86c  trigy  real array of size 2*(ny+1)      contains trig tables for y transforms
87c  trigz  real array of size 2*nz          contains trig tables for z transforms
88c  wn     complex array of size nz/4 + 1   auxilliary trig info for sine/cosine
89c  ifax       integer array of size 13         factorization tables for FFTs
90c  ifay       integer array of size 13         factorization tables for FFTs
91c  ifaz       integer array of size 13         factorization tables for FFTs
92c
93c  Scratch space:
94c  work       real scratch array dimensioned in variable_declarations.h
95c  xt         complex array of size (nx+2,nz/2+1)
96c
97c  Output:
98c
99c  x_cplx      complex array of frequency data for iswitch=1
100c  x           real array of physical space data for iswitch=-1
101c
102c N.B.         Global real data "x" has size (nx+2,ny+1,nz+1) 
103c              of which (nx,ny,nz+1)
104c              elements define the periodic sequences on the spatial grid.
105c              Complex data "x_cplx" has global size (nx/2+1,ny+1,nz+1) 
106c              Each processor stores a portion of the input and
107c              output arrays. See real and complex data maps.
108c
109c$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
110      implicit none
111      integer i,j,k,kend,myid,numprocs,locnx,locnz
112      integer comm,twoslice,subslice,ierr
113      integer num_dims,plane,npz,nx,ny,nz,nxp2,nyp1   
114      integer ifax(13),ifay(13),ifaz(13),iswitch,isign,itrig,nyplanes
115      integer lotx,loty,lotz,incx,incy,incz,jumpx,jumpy,jumpz
116      real trigx(3*(nx+2)/2+1),trigy(2*(ny+1)),trigz(2*nz),pi,xnorm
117      real x(nx+2,ny+1,locnz+1),work(1)
118      complex arg ,wn(nz/4+1),xt(nx+2,nz/2+1)
119      complex x_cplx(locnx,ny+1,nz+1)
120      complex scratch(locnx,ny+1,nz+1)
121      character*1 tswitch
122c
123c
124      pi = 4.*atan(1.)
125      nxp2 = nx + 2
126      nyp1 = ny + 1  ! note nyp1=0+1=1 for 2d problem
127      npz = nz/2
128
129c
130c   Initialize trig arrays for the ffts. This code executes only if itrig=1.
131c   After execution, the results are passed back to the calling routine and
132c   remain usable if the arrays are not overwritten. itrig is then set to 0
133c   so that trig initialization is only performed once.
134c
135      if( itrig .eq. 1 ) then
136       call fftfax (nx,ifax,trigx)
137       if( num_dims .eq. 3 ) call cftfax (ny,ifay,trigy)
138       if( tswitch .eq. 's' .or. tswitch .eq. 'c' ) then
139        call cftfax (npz,ifaz,trigz)  ! for sin/cos transforms via 5&6&7
140        do i = 1, nz/4+1
141         arg = pi * (i-1)/(nz/2.0)
142         wn(i) = cos(arg) + (0.0,1.0)*sin(arg)
143        enddo
144       elseif( tswitch .eq. 'f' .or. tswitch .eq. 'F' ) then
145        call cftfax (nz,ifaz,trigz) ! for complex vertical fourier transforms
146       endif
147       if( myid .eq. 0 ) then
148        write(6,*) 'trig tables set up '
149       endif
150       itrig = 0    ! flag indicating that setup calculations have been done
151      endif
152
153      if (iswitch .le. 0) go to 60   ! i.e. do inverse transform
154
155
156cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
157c   Forward transforms: (real data to frequency components)
158cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
159
160c     Number of horizontal planes in each slab
161      if( myid .eq. numprocs-1 ) then
162       kend=locnz+1
163      else
164       kend=locnz
165      endif
166
167      if( num_dims .eq. 3 ) then
168c     For 3d problems do x then y transforms for each xy plane:
169c
170c                      ! real to complex x transforms
171      isign = -1       ! forward transform flag for Temperton package
172      incx = 1         ! words between adjacent elements in a transform
173      jumpx = nxp2     ! real words between successive first elements
174      lotx = ny        ! number of x transforms to do
175      do k = 1,kend    ! Fourier transform in x for each horizontal plane
176       call fft991 (x(1,1,k),work,trigx,ifax,incx,jumpx,nx,lotx,isign)
177      enddo
178c
179c     complex to complex transforms in the y direction
180c
181       incy = nxp2/2    ! complex words between successive elements
182       jumpy = 1        ! complex words between adjacent elements in a transform
183       loty = nxp2/2    ! number of complex y transforms to do
184       do k = 1,kend    ! Fourier transform in y
185        call cfft99 (x(1,1,k),work,trigy,ifay,incy,jumpy,ny,loty,isign)
186       enddo
187      elseif( num_dims .eq. 2 ) then  ! do all x transforms in a single call
188c                                     ! no y transforms required
189c                       ! Do real to complex transforms in x direction
190       isign = -1       ! forward transform flag for Temperton package
191       incx = 1         ! words between adjacent elements in a transform
192       jumpx = nxp2     ! real words between successive first elements
193       lotx = kend      ! number of x transforms to do
194       do j = 1,1       ! Fourier transform in x for each j(xz) plane
195        call fft991 (x(1,j,1),work,trigx,ifax,incx,jumpx,nx,lotx,isign)
196       enddo
197     
198      endif
199
200c
201c    z transforms in xz plane -- determine number of planes
202c     
203      if( num_dims .eq. 3 ) then
204       nyplanes=ny
205      elseif( num_dims .eq. 2) then
206       nyplanes=1
207      endif
208
209
210c  *****    EXCHANGE DATA BETWEEN PROCESSORS SO THAT EACH  ***************
211c           PROCESSOR HOLDS A "COLUMN" OF DATA RATHER THAN A "SLAB"
212      call slabs_to_columns(x,x_cplx,nx,ny,nz,locnx,locnz,numprocs,
213     *                      myid,comm,twoslice,subslice,work)
214c*************************************************************************
215 
216
217c Do sine/cosine/fourier transforms in z direction, sine and cosine transforms 
218c are their own inverses and use isign=+1 by convention
219c
220     
221      if ((tswitch .eq. 'C') .or. (tswitch .eq. 'c')) then
222       isign = +1
223       incz = 2*locnx      ! words between adjacent elements in a transform
224       jumpz = 1           ! real words between successive first elements
225       lotz = 2*locnx      ! number of z transforms to do 
226       do  j = 1,nyplanes   ! for each x-z plane of data
227        plane = j               ! cosine transform in z
228        call six (x_cplx, 2*locnx, ny, nz, plane, wn, xt, work,
229     *            trigz, ifaz, incz, jumpz, npz, lotz, isign)
230       enddo
231      elseif((tswitch .eq. 'S') .or. (tswitch .eq. 's')) then
232       isign = +1
233       incz = 2*locnx      ! words between adjacent elements in a transform
234       jumpz = 1           ! real words between successive first elements
235       lotz = 2*locnx      ! number of z transforms to do 
236       do j = 1, nyplanes
237        plane = j               ! sine transform in z
238        call seven (x_cplx, 2*locnx, ny, nz, plane, wn, xt, 
239     *             work, trigz, ifaz, incz, jumpz, npz, lotz, isign)
240        enddo
241      elseif((tswitch .eq. 'F') .or. (tswitch .eq. 'f')) then  ! Fourier transform
242       isign=-1
243       incz = locnx*(ny+1)      ! words between adjacent elements in a transform
244       jumpz = 1                ! words between successive first elements
245       lotz = locnx             ! number of z transforms to do 
246       do j = 1, nyplanes   ! Complex Fourier transform in z
247        call cfft99 (x_cplx(1,j,1),work,trigz,ifaz,incz,jumpz,nz,lotz,isign)
248       enddo
249      endif
250
251c
252c  Normalize the results
253c 
254      if( num_dims .eq. 3 ) then
255       if( tswitch .eq. 's' ) xnorm = float(nz)/(2.*ny)
256       if( tswitch .eq. 'c' ) xnorm = float(nz)/(2.*ny)
257       if( tswitch .eq. 'f' ) xnorm = 1./float(ny*nz)   
258      elseif( num_dims .eq. 2 ) then
259       if( tswitch .eq. 's' ) xnorm = float(nz)/2.
260       if( tswitch .eq. 'c' ) xnorm = float(nz)/2.       
261       if( tswitch .eq. 'f' ) xnorm = 1./float(nz) 
262      endif
263     
264      do k = 1, nz+1   
265       do j = 1,nyp1    ! nyp1=1 for 2d problem
266        do i = 1,locnx
267         x_cplx(i,j,k) = x_cplx(i,j,k)*xnorm
268        enddo
269       enddo
270      enddo
271     
272      return
273
274
275ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
276c   Perform the inverse transform (frequency components to real data)
277ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
27860      continue
279 
280c    inverse z transforms in xz plane -- determine number of planes
281       
282      if( num_dims .eq. 3 ) then
283       nyplanes=ny
284      elseif( num_dims .eq. 2) then
285       nyplanes=1
286      endif
287
288c    make a copy of the input data so it can be left unaltered
289      do k=1,nz+1
290       do j=1,nyplanes
291        do i=1,locnx
292         scratch(i,j,k)=x_cplx(i,j,k)
293        enddo
294       enddo
295      enddo
296
297c
298c Do inverse sin/cos/fourier transforms in z direction, 
299c sine and cosine transforms 
300c are their own inverses and use isign=+1 by convention
301c
302      if ((tswitch .eq. 'C') .or. (tswitch .eq. 'c')) then
303       isign = +1
304       incz = 2*locnx      ! words between adjacent elements in a transform
305       jumpz = 1           ! real words between successive first elements
306       lotz = 2*locnx      ! number of z transforms to do
307        do j = 1,nyplanes       ! for each x-z plane of frequency data
308         plane = j                     ! inverse cosine transform in z
309         call six (scratch, 2*locnx, ny, nz, plane, wn, xt, work,
310     *             trigz, ifaz, incz, jumpz, npz, lotz, isign)
311        enddo
312      elseif ((tswitch .eq. 'S') .or. (tswitch .eq. 's')) then
313       isign = +1
314       incz = 2*locnx      ! words between adjacent elements in a transform
315       jumpz = 1           ! real words between successive first elements
316       lotz = 2*locnx      ! number of z transforms to do
317        do j = 1,nyplanes
318         plane = j                     ! inverse sine transform in Z 
319         call seven (scratch, 2*locnx, ny, nz, plane, wn, xt, 
320     *              work, trigz, ifaz, incz, jumpz, npz, lotz, isign)
321        enddo
322      elseif ((tswitch .eq. 'F') .or. (tswitch .eq. 'f')) then
323       isign = +1
324       incz = locnx*(ny+1)      ! words between adjacent elements in a transform
325       jumpz = 1                ! real words between successive first elements
326       lotz = locnx             ! number of z transforms to do
327       do j = 1, nyplanes   ! Complex Fourier transform in z
328        call cfft99 (scratch(1,j,1),work,trigz,ifaz,incz,jumpz,nz,lotz,isign)
329       enddo
330      endif
331
332c  *****    EXCHANGE DATA BETWEEN PROCESSORS SO THAT EACH  ***************
333c           PROCESSOR HOLDS A "SLAB" OF DATA RATHER THAN A "COLUMN"
334      call columns_to_slabs(x,scratch,nx,ny,nz,locnx,locnz,numprocs,
335     *                      myid,comm,twoslice,subslice,work)
336c*************************************************************************
337 
338c     Number of horizontal planes in each slab
339      if( myid .eq. numprocs-1 ) then
340       kend=locnz+1
341      else
342       kend=locnz
343      endif
344
345c   zero out the k nyquist positions prior to inverse transforming
346      do i=nx+1,nx+2
347       do j=1,nyplanes
348        do k=1,kend
349         x(i,j,k)=0.0
350        enddo
351       enddo
352      enddo
353
354c   inverse Fourier transform in y if num_dims=3
355c
356      if( num_dims .eq. 3 ) then   ! inverse transform in y then x
357       isign = +1
358       incy = nxp2/2  ! complex words between successive first elements
359       jumpy = 1      ! complex words between adjacent elements in a transform
360       loty = nxp2/2  ! number of complex y transforms to do
361       do k = 1,kend  ! inverse Fourier transform in y for each horiz. plane
362        call cfft99 (x(1,1,k),work,trigy,ifay,incy,jumpy,ny,loty,isign)
363       enddo
364c
365c     inverse Fourier transform in x
366c
367       isign=+1
368       incx = 1        ! real words between adjacent elements in a transform
369       jumpx = nxp2    ! real words between successive first elements
370       lotx = ny       ! number of x transforms to do
371       do k = 1,kend   ! inverse Fourier transform in x for each horiz. plane
372        call fft991 (x(1,1,k),work,trigx,ifax,incx,jumpx,nx,lotx,isign)
373       enddo
374      elseif( num_dims .eq. 2 ) then  ! do all x transforms in a single call
375c                                     ! no y transforms required
376c                     ! Do real to complex transforms in x direction
377       isign = +1     ! inverse transform flag for Temperton package
378       incx = 1       ! words between adjacent elements in a transform
379       jumpx = nxp2   ! real words between successive first elements
380       lotx = kend    ! number of x transforms to do
381       do j = 1,1     ! Fourier transform in x for each j(xz) plane
382        call fft991 (x(1,j,1),work,trigx,ifax,incx,jumpx,nx,lotx,isign)
383       enddo
384      endif
385c
386      return
387      end
388       
389       
390      subroutine five (c, nsets, n, wn, work, trig, ifa,
391     *                 inc, jump, np, lot, isign)
392
393C-----------------------------------------------------------------------------
394C
395C five.f - This FORTRAN subroutine computes the inverse Fourier Transform
396C          of a number of sets of conjugate even data. Input consists of 
397C          nsets vectors of n+1 complex elements of conjugate even data.
398C          Output consists of nsets vectors of n complex  elements containing
399C          the results of the inverse transform.  Since the input data is
400C          conjugate even, the results from the transform are real.  Actually,
401C          these "real" results are stored in alternating real and imaginary 
402C          components of the output vectors.
403C
404C              Note that the inverse transform in this routine utilizes
405C          the Temperton FFT package.
406C
407C          Procedure Five: as discussed in
408C              Cooley's paper in the Journal of Sound Vibration (1970), 12(3),
409C          pg. 315-337.
410C
411c       code written by Kraig Winters July 1 1990
412c   this is a modified version of Bryan Johns/KW code
413C
414C       input: c (complex array of nsets by n+1) - contains the sets of
415C             input conjugate even data
416C              nsets (integer) - number of sets of data to be inverse transformed
417C              n (integer) - number of elements resulting from the inverse
418C                                       transform
419C              wn (complex array of n/2+1) - contains the complex exponential
420C                                               tables required by this routine
421C                  work (real array) - work array required by the Temperton package
422C              trig (real array of np) - contains trig tables required by the
423C                                                      Temperton package
424C              ifa (integer array of 13) - contains factorization tables
425C                                          required by the Temperton package
426C              inc (integer) - indicates direction of inverse transform
427C              jump (integer) - distance to next data sets in the input array
428C              np (integer) - number of data in each data set
429C              lot (integer) - number of data sets to be inverse transformed
430C              isign (integer) - indicates forward or inverse transform
431C                     (for this routine, should be inverse: isign = +1)
432C
433C       output: c (complex array of nsets by n+1) - contains the results
434C                                of the inverse transform
435C                       (NOTE: only nsets by n elements are used in output)
436C------------------------------------------------------------------------------
437
438      integer nsets, n, np
439      complex c(nsets,n+1), wn(n/2+1), a1, a2
440      real work(1), trig(np)
441      integer ifa(13), i, k
442      integer inc, jump, lot, isign, npt, nb2, nb2p1
443
444      npt = n
445      nb2 = npt/2
446      nb2p1 = nb2+1
447
448c
449c  Compute the input to the inverse Fourier transform "c"
450c
451
452        do i = 1, nsets
453         a1 = c(i,1) + conjg(c(i,npt+1))
454         a2 = (c(i,1) - conjg(c(i,npt+1))) * wn(1)
455         c(i,1) = a1 + (0.0,1.0)*a2
456          do k = 2, nb2
457           a1 = c(i,k) + conjg(c(i,npt+2-k))
458           a2 = (c(i,k) - conjg(c(i,npt+2-k))) * wn(k)
459           c(i,k) = a1 + (0.0,1.0)*a2
460           c(i,npt+2-k) = conjg(a1 - (0.0,1.0)*a2)
461          enddo
462         a1 = c(i,nb2p1) + conjg(c(i,nb2p1))
463         a2 = (c(i,nb2p1) - conjg(c(i,nb2p1))) * wn(nb2p1)
464         c(i,nb2p1) = a1 + (0.0,1.0)*a2
465        enddo
466
467c
468c   Inverse Fourier transform the array "c"
469c
470        call cfft99 (c, work, trig, ifa, inc, jump, np, lot, isign)
471
472        return
473        end
474
475
476
477      subroutine six (x, nxp2, ny, nz, plane, wn, xt, work,
478     *                trigz, ifaz, incz, jumpz, npz, lotz, isign)
479
480C------------------------------------------------------------------------------
481C
482C six.f - This FORTRAN subroutine computes the Fourier cosine transform
483C         in the z direction of a number of sets of data in a particular
484C         x-z plane of 3-D data. 
485C
486C         Input consists of nxp2 vectors of data of length nz+1 in the plane.
487C         Output are npx2 vectors of length nz+1 containing the coefficients of
488C         the cosine transform for each vector of data in the plane.  The
489C         coefficients are overwritten onto the input data.
490C
491C         This routine is an implementation of
492C         Procedure Six as described in Cooley's paper in the Journal of
493C         Sound Vibration, (1970) 12(3), pg. 315-337. 
494C         This procedure allows a cosine transform to be performed via 
495C         a Fourier transform routine but using only 1/4 of the input data.
496C
497C         This routine utilizes the Temperton FFT package to perform the
498C         required Fourier transforms.
499C
500C   N.B.: This routine must be linked to five.f and the Temperton FFT package. 
501C         
502C
503c       code written by Kraig Winters July 1 1990
504c       this is a modified version of Bryan Johns/KW code
505C
506C       input: x (real array of nxp2 by ny+1 by nz+1) - contains input data
507C          nxp2 (integer) - number of vectors in the plane to be transformed
508C          ny (integer) - number of x-z planes in x array
509C          nz (integer) - length of each vector in the z direction
510C              plane (integer) - indicates which x-z plane in x to transform
511C          wn (complex array of nz/4+1) - contains complex exponential table
512C              xt (complex array of nxp2 by nz/2+1) - work array containing 
513C          x tilda terms required as input to Procedure five
514C          work (real array of nxp2*(ny+1)*nz) - work array required by
515C                Temperton FFT package
516C          trigz (real array of npz) - contains trig tables in z direction
517C                           required by Temperton package
518C          ifaz (integer array of 13) - contains factorization tables
519C                           required by Temperton package
520C          incz (integer) - indicates direction of cosine transform in
521C                               the array x
522C          jumpz (integer) - distance between vectors in the plane
523C          npz (integer) - number of data in each vector
524C          lotz (integer) - number of vectors of data in the plane
525C          isign (integer) - indicates forward or inverse transform
526C                                     (should be inverse : isign = +1) 
527C 
528C       output: x - contains cosine coefficients of input data
529C
530C-------------------------------------------------------------------------------
531
532        integer nxp2, ny, nz, plane, incz, jumpz, npz, lotz, isign
533        integer ifaz(13)
534        real x(nxp2, ny+1, nz+1), work(1), trigz(npz)
535        real a1, a2, sum, pi
536        complex xt(nxp2,nz/2+1)
537        complex wn(nz/4+1)
538        integer i,k,n
539
540        n = nz/2
541        pi = 4.*atan(1.)
542
543C+
544C  Compute a complex conjugate even sequence for each real vector of data
545C    (in Cooley's paper, these are the x tilda / N terms)
546C    (NOTE: we only need to form the first nz/2+1 of them because of symmetry)
547C-
548      do i = 1, nxp2
549       xt(i,1) = cmplx(x(i,plane,1)/nz, 0.0)
550        do k = 2, n   
551         xt(i,k) = cmplx(x(i,plane,2*k-1)/nz,
552     *                  (x(i,plane,2*k-2) - x(i,plane,2*k))/nz)
553        enddo
554       xt(i,n+1) = cmplx(x(i,plane,nz+1)/nz,0.0)
555      enddo
556C+
557C  Inverse transform the conjugate even sequence into a real sequence using
558C       Procedure Five as outlined in Cooley's paper
559C-
560      call five (xt, nxp2, n, wn, work, trigz, ifaz, incz,
561     *           jumpz, npz, lotz, isign)
562
563C+
564C  Post-process the results to form the cosine coefficients
565C          (see Cooley's Paper for the details here)
566C-
567       do 100 i = 1, nxp2
568            a1 = real(xt(i,1))
569            sum = 0.0
570            do 20 k = 2, nz, 2
571                 sum = sum + x(i,plane,k)
57220      continue
573            a2 = 2.0*sum/nz
574            x(i,plane,1) = a1 + a2
575            x(i,plane,nz+1) = a1 - a2
576            do 30 k = 2, nz-2, 2
577                  x(i,plane,k) = 0.5 * ((aimag(xt(i,k/2)) +
578     &                       aimag(xt(i,(nz+2-k)/2))) -
579     &                   (aimag(xt(i,k/2)) - aimag(xt(i,(nz+2-k)/2))) /
580     &                            (2.0*sin((k-1)*pi/nz)))
581        x(i,plane,k+1) = 0.5 * ((real(xt(i,k/2+1)) +
582     &                           real(xt(i,(nz+1-k)/2+1))) -
583     &                 (real(xt(i,k/2+1)) - real(xt(i,(nz+1-k)/2+1))) /
584     &                          (2.0*sin(k*pi/nz)))
58530          continue
586            x(i,plane,nz) = 0.5 * ((aimag(xt(i,nz/2)) + aimag(xt(i,1))) -
587     &                           (aimag(xt(i,nz/2)) - aimag(xt(i,1))) /
588     &                            (2.0*sin((nz-1)*pi/nz)))
589100     continue
590       
591        return
592        end
593
594
595        subroutine seven (x, nxp2, ny, nz, plane, wn, xt, work,
596     &                  trigz, ifaz, incz, jumpz, npz, lotz, isign)
597
598C------------------------------------------------------------------------------
599C
600C seven.f - This FORTRAN subroutine computes the Fourier sine transform
601C         in the z direction of a number of sets of data in a particular
602C         x-z plane of 3-D data. 
603C
604C         Input consists of nxp2 vectors of data of length nz+1 in the plane.
605C         Output are npx2 vectors of length nz+1 containing the coefficients of
606C         the sine transform for each vector of data in the plane.  The
607C         coefficients are overwritten onto the input data.
608C
609C         This routine is an implementation of
610C         Procedure Seven as described in Cooley's paper in the Journal of
611C         Sound Vibration, (1970) 12(3), pg. 315-337. 
612C         This procedure allows a sine transform to be performed via 
613C         a Fourier transform routine but using only 1/4 of the input data.
614C
615C         This routine employs the Temperton FFT package to perform the
616C         required Fourier transforms.
617C
618C   N.B. This routine must be linked to five.f and the Temperton FFT package. 
619C
620c       code written by Kraig Winters July 1 1990
621c   this is a modified version of Bryan Johns/KW code
622
623C
624C       input: x (real array of nxp2 by ny+1 by nz+1) - contains input data
625C          nxp2 (integer) - number of vectors in the plane to be transformed
626C          ny (integer) - number of x-z planes in x array
627C          nz (integer) - length of each vector in the z direction
628C              plane (integer) - indicates which x-z plane in x to transform
629C          wn (complex array of nz/4+1) - contains complex exponential table
630C              xt (complex array of nxp2 by nz/2+1) - work array containing 
631C          x tilda terms required as input to Procedure five
632C          work (real array of nxp2*(ny+1)*nz) - work array required by
633C                           Temperton FFT package
634C          trigz (real array of npz) - contains trig tables in z direction
635C                           required by Temperton package
636C          ifaz (integer array of 13) - contains factorization tables
637C                           required by Temperton package
638C          incz (integer) - indicates direction of sine transform in
639C                               the array xt
640C          jumpz (integer) - distance between vectors in the plane
641C          npz (integer) - number of data in each vector
642C          lotz (integer) - number of vectors of data in the plane
643C          isign (integer) - indicates forward or inverse transform
644C                                     (should be inverse : isign = +1) 
645C 
646C       output: x - contains sine coefficients of input data
647C
648C----------------------------------------------------------------------------
649
650        integer nxp2, ny, nz, plane, incz, jumpz, npz, lotz, isign
651        integer ifaz(13)
652        real x(nxp2, ny+1, nz+1), work(1), trigz(npz)
653        real pi
654        complex xt(nxp2,nz/2+1)
655        complex wn(nz/4+1)
656        integer i,k,n
657
658        n = nz/2
659        pi = 4.*atan(1.)
660
661C+
662C  Compute a complex conjugate even sequence for each real vector of data
663C    (in Cooley's paper, these are the x tilda / N terms)
664C    (NOTE: we only need to form the first nz/2+1 of them because of symmetry)
665C-
666      do i = 1, nxp2
667       xt(i,1) = cmplx(-2.0*x(i,plane,2)/nz, 0.0)
668       do k = 2, n   
669        xt(i,k) =
670     *            cmplx ((x(i,plane,2*k-2) - x(i,plane,2*k))/nz,
671     *              -x(i,plane,2*k-1)/nz)
672       enddo
673           xt(i,n+1) = cmplx(2.0*x(i,plane,nz)/nz,0.0)
674      enddo
675
676C+
677C  Inverse transform the conjugate even sequence into a real sequence using
678C       Procedure Five as outlined in Cooley's paper
679C-
680      call five (xt, nxp2, n, wn, work, trigz, ifaz, incz,
681     *           jumpz, npz, lotz, isign)
682
683C+
684C  Post-process the results to form the sine coefficients
685C          (see Cooley's Paper for the details here)
686C-
687        do 100 i = 1, nxp2
688            x(i,plane,1) = 0.0 
689            x(i,plane,nz+1) = 0.0
690            do 30 k = 2, nz-2, 2
691                  x(i,plane,k) = 0.5 * ((aimag(xt(i,k/2)) - 
692     &                       aimag(xt(i,(nz+2-k)/2))) -
693     &                  (aimag(xt(i,k/2)) + aimag(xt(i,(nz+2-k)/2))) /
694     &                            (2.0*sin((k-1)*pi/nz)))
695        x(i,plane,k+1) = 0.5 * ((real(xt(i,k/2+1)) - 
696     &                           real(xt(i,(nz+1-k)/2+1))) -
697     &                 (real(xt(i,k/2+1)) + real(xt(i,(nz+1-k)/2+1))) /
698     &                          (2.0*sin(k*pi/nz))) 
69930          continue
700            x(i,plane,nz) = 0.5 * ((aimag(xt(i,nz/2)) - aimag(xt(i,1))) -
701     &                           (aimag(xt(i,nz/2)) + aimag(xt(i,1))) /
702     &                            (2.0*sin((nz-1)*pi/nz)))
703100     continue
704       
705        return
706        end
707
Note: See TracBrowser for help on using the repository browser.