TreeMig Code
Loading...
Searching...
No Matches
GFTConvolution2D.f90
Go to the documentation of this file.
1!==============================================================================
36!==============================================================================
37SUBROUTINE gft2dconvolution(isp, ny,mx,niy,mjx, spatDataIn,kernelTransf,spatDataOut)
38 USE gft, only: gft_prec, gft_rcr, gft_set_fft, gft_do_fft, gft_end_fft
39 IMPLICIT NONE
40 INTEGER, INTENT(IN):: isp ! > species index
41 INTEGER, INTENT(IN):: ny,mx,niy,mjx ! > actual and maximal dimensions
42 COMPLEX(kind=GFT_Prec), DIMENSION(0:niy/2,mjx), INTENT(IN) :: kernelTransf
43 REAL(kind=gft_prec), DIMENSION(0:ny-1,mx), INTENT(IN) :: spatdatain
44 REAL(kind=gft_prec), DIMENSION(0:ny-1,mx), INTENT(OUT):: spatdataout
45 ! > REAL(kind=GFT_Prec), DIMENSION(0:ny-1,mx) :: spatDataOutTest
46
47 REAL(kind=gft_prec), DIMENSION(0:niy-1,mjx) :: spatdatainhelp
48 REAL(kind=gft_prec), DIMENSION(0:niy-1,mjx) :: spatdataouthelpwithkernel
49 REAL(kind=gft_prec) :: sc , ratio
50 COMPLEX(kind=GFT_Prec), DIMENSION(0:niy/2,mjx) :: spatDataTransf,spatDataTransfWithKernel
51
52 TYPE(gft_rcr) :: rcr
53
54 INTEGER :: ilat, ilon, nstart_y, nend_y, mstart_x, mend_x, dimx,dimy
55
56 ! > Here, an additional Filter to get rid of the noise can be created. Currently not used
57 ! > CALL LowPassFilter( 0, niy/2, 1, mjx , 1., filter)
58
59 ! >settings
60 dimx=mx ! > For GFT_set; the FFT will be done on an intermediate area (ny x mx) that is larger than
61 dimy=ny ! > the simulation area (maxlon x maxlat) and embedded in a very large area (niy x mix) for zero padding
62
63 ! > Spatial data file is padded, i.e. extended to a "good" size by zeros
64
65 ! > bounds where intermediate area is stored in the large area; in corner! >
66 nstart_y = 0; nend_y = ny-1
67 mstart_x = 1; mend_x = mx
68
69 ! > call PrintMatrixASXY2File(spatDataIn, 0,ny-1, 1,mx, "spatDataIn" )
70
71 ! > Here the intermediate area is stored in the corner of the large area.
72 spatdatainhelp(0:,:) =0
73 spatdatainhelp(nstart_y : nend_y, mstart_x : mend_x )=spatdatain
74
75 ! > call PrintMatrixASXY2File(spatDataInHelp,0,niy-1,1,mjx,"spatDataInHelp" )
76
77 ! > Preparation of FFTs
78
79 CALL gft_set_fft(nx=dimy, ny=dimx, fft=rcr) ! > x and y exchanged on purpose, because Nx refers to the first dimension
80
81 ! >... forward FFT; transformation from REAL input ** kernel kernelTransf is already transformed and passed *************************
82
83 ! > This is the call to transform the spatial seed production data
84
85 sc = 1.0_gft_prec/real(dimx*dimy , kind=gft_prec)
86 CALL gft_do_fft(fft=rcr, isign= -1, scale=sc, r_in=spatdatainhelp, c_out=spatdatatransf)
87
88! > print *, "nach forward transformation"
89
90 ! > call PrintMatrixASXY2File(ABS(spatDataTransf), 0, niy/2, 1,mjx, "ABSspatDataTransf" )
91
92
93! > Actual convolution by multiplication of the two transforms
94 spatdatatransfwithkernel = spatdatatransf * kerneltransf
95! >
96
97 ! > call PrintMatrixASXY2File(ABS(kernelTransf ), 0, niy/2, 1,mjx, "ABSkernelTransf" )
98 ! > call PrintMatrixASXY2File(ABS(spatDataTransfWithKernel), 0, niy /2, 1,mjx, "ABSspatDataTransfWithKernel" )
99
100
101! > This is the backtransform of the convolution
102 ! >... backward FFT ; transformation back to space domain
103
104 sc = 1.0_gft_prec ! >* REAL(1.+ sc_bwd * (precfac - 1.), KIND(GFT)
105 CALL gft_do_fft(fft=rcr, isign=1, scale=sc, c_in=spatdatatransfwithkernel, r_out=spatdataouthelpwithkernel)
106
107 ! > call PrintMatrixASXY2File(spatDataOutHelpWithKernel,0,niy-1,1,mjx, "spatDataOutHelpWithKernel" )
108
109! > Some cleaning: negative and very low values are interpreted as noise and set to zero
110 do ilat = 0, niy-1 ! > y, lat
111 do ilon = 1, mjx ! >1, m! > x, lon
112 if (spatdataouthelpwithkernel(ilat, ilon) < 0 ) spatdataouthelpwithkernel(ilat, ilon)=0 ! > mean trick
113 if (spatdataouthelpwithkernel(ilat, ilon) < 1.0e-10 ) spatdataouthelpwithkernel(ilat, ilon)=0 ! > mean trick
114 END DO
115 END DO
116
117 ! > Get the target area out of the large area
118 spatdataout=spatdataouthelpwithkernel(nstart_y : nend_y, mstart_x : mend_x )
119
120 ! > To make sure that all seeds are distributed the seedrain is scaled that its sum is the sum of the produced seeds
121 ratio=sum(spatdatain)/sum(spatdataout)
122
123 spatdataout=spatdataout*ratio ! > Hm, for some reason the seed rain is scaled, probably for distributing exactly all seeds in the area
124
125 ! > call PrintMatrixASXY2File(spatDataOut, 0,ny-1, 1,mx, "spatDataOut" )
126 ! >... Free rcr objects
127 CALL gft_end_fft(fft=rcr)
128
129 END SUBROUTINE gft2dconvolution
130
131!==============================================================================
165!==============================================================================
166SUBROUTINE gft2dtransformkernel(ny, mx, niy, mjx, y_dim_kernel, x_dim_kernel, kernelIn, kernelTransf )
167 USE gft, only: gft_rcr, gft_prec, gft_set_fft, gft_do_fft, gft_end_fft
168 IMPLICIT NONE
169
170 INTEGER, INTENT(IN):: ny, mx, niy, mjx, y_dim_kernel, x_dim_kernel
171
172 REAL (kind=gft_prec), DIMENSION(0:(y_dim_kernel-1),x_dim_kernel ), INTENT(IN):: kernelin
173
174 COMPLEX(kind=GFT_Prec), DIMENSION(0:(niy/2),mjx), INTENT(OUT) :: kernelTransf
175
176 REAL (kind=gft_prec), DIMENSION(0:(niy-1),mjx) :: kernel,kernel1
177 REAL (kind=gft_prec), DIMENSION(0:(ny-1),mx) :: mediumsizekernel
178 REAL (kind=gft_prec), DIMENSION(0:(ny-1),mx) :: reorderedkernel
179 REAL (kind=gft_prec) :: sc
180 INTEGER :: edge_y, edge_x,edge_y_sm, edge_x_sm, code, dimy,dimx
181
182 TYPE(gft_rcr) :: rcr
183
184 dimy= ny; dimx=mx;
185! > print *, "in GFT2DTransformKernel spec, dimy, dimx, niy, mjx ", dimy, dimx, niy, mjx
186 ! > store small kernel to medium area dimensions
187 edge_y = -1
188 edge_x = 0
189 kernel(0:,:)=0; kernel1(0:,:)=0;
190! > print *, "edges",edge_y , edge_x,"lengths",niy, mjx, "y_dim_kernel, x_dim_kernel",y_dim_kernel, x_dim_kernel
191 ! > reorder kernel, center to corners
192 ! > store shifted kernel central to medium size array of size ny x mx
193 mediumsizekernel(:,:)=0.
194 edge_y_sm = (dimy - y_dim_kernel)/2 ! > edges of intermediate area from where on kernel is stored
195 edge_x_sm = (dimx - x_dim_kernel)/2 ! > edges of intermediate area from where on kernel is stored
196 mediumsizekernel( (edge_y_sm +1 ):(edge_y_sm + y_dim_kernel) , (edge_x_sm + 1):(edge_x_sm + x_dim_kernel)) = kernelin
197 ! > call PrintMatrixASXY2File(mediumsizekernel, 0,dimy-1, 1,dimx, "mediumsizekernel" )
198 ! > reorder the kernel on the mediumsized array, center to corners and vice versa
199 CALL reorderkernelforgft(dimy,dimx, mediumsizekernel,reorderedkernel ) ! >
200 ! > call PrintMatrixASXY2File(reorderedkernel, 0,dimy-1, 1,dimx, "reorderedkernel" )
201 ! > reordered kernel is put in very large extended area, at corners
202 kernel((edge_y+1):(edge_y+dimy),(edge_x+1):(edge_x+dimx))= reorderedkernel
203 ! > call PrintMatrixASXY2File(kernel, 0,niy-1, 1,mjx, "expanded_kernel" )
204 ! > Preparation of FFT
205
206 CALL gft_set_fft(nx=dimy, ny=dimx, fft=rcr, code=code) ! >Although the large area is greater, the dimensions are set to those of the medium size. On purpose x and y exchanged! >
207
208 ! >... forward FFT; transformations from REAL to complex
209 sc = 1.0_gft_prec/real(dimx*dimy , kind=gft_prec)
210! > print *, "sc", sc
211! > This is the forward transformation of the kernel
212 CALL gft_do_fft(fft=rcr, isign=-1 , scale=sc, r_in=kernel, c_out=kerneltransf)
213 ! > call PrintMatrixASXY2File(ABS(kernelTransf), 0, niy/2, 1,mjx, "ABSkernelTransf1" )
214 CALL gft_end_fft(fft=rcr)
215 END SUBROUTINE gft2dtransformkernel
216
217!==============================================================================
235!==============================================================================
236SUBROUTINE setdimsforfft(ispec)
237 USE all_par, ONLY: spec, maxlat, maxlon
238 IMPLICIT NONE
239 INTEGER, INTENT(IN):: ispec
240 INTEGER :: safety_margin, &
241 maxlatEven, maxlonEven, maxlatExt, maxlonExt, maxlatEvenExt, maxlonEvenExt
242 ! > a buffer of one radius of the kernel is put to the simulation area. Not around but only to two sides
243 safety_margin = spec(ispec)%rad
244 ! > next even number including the safety_margin
245 maxlateven= ((maxlat + safety_margin - 1) / 2) * 2 + 2
246 maxloneven= ((maxlon + safety_margin - 1) / 2) * 2 + 2
247 ! > next power of two of this buffered area, for the intermediate area
248 maxlonevenext=2**ceiling(log(1.*maxloneven)/log(2.))
249 maxlatevenext=2**ceiling(log(1.*maxlateven)/log(2.))
250 ! > and another power of two for the large extended area
251 maxlatext=2**(1+ceiling(log(maxlatevenext*1.)/log(2.))) ! > next power of two
252 maxlonext=2**(1+ceiling(log(maxlonevenext*1.)/log(2.))) ! > next power of two
253 ! >maxlatExt =2 * maxlatEvenext ! > next power of two
254 ! >maxlonExt =2 * maxlonEvenext ! > next power of two
255
256 print *, "ispec, maxlat, maxlatEvenext(ny),maxlatExt(niy), ", ispec, maxlat,maxlatevenext, maxlatext
257 print *, "ispec, maxlon, maxlonEvenext(mx),maxlonExt(mjx)", ispec, maxlon,maxlonevenext, maxlonext
258 ! > the dimensions are species specific and stored in the spec object
259 spec(ispec)%maxlatExt = maxlatext
260 spec(ispec)%maxlonExt = maxlonext
261 spec(ispec)%maxlatEvenExt = maxlatevenext
262 spec(ispec)%maxlonEvenExt = maxlonevenext
263 END SUBROUTINE setdimsforfft
264
265!==============================================================================
282!==============================================================================
283 SUBROUTINE lowpassfilter(dimy_start, dimy_end, dimx_start, dimx_end , filterexpo, filter)
284 USE gft, only: gft_prec
285 IMPLICIT NONE
286
287 INTEGER, INTENT(IN):: dimy_start, dimy_end, dimx_start, dimx_end
288 REAL, INTENT(IN) :: filterexpo
289 COMPLEX(kind=GFT_Prec),DIMENSION(dimy_start:dimy_end,dimx_start:dimx_end), INTENT(OUT):: filter
290
291 REAL(kind=gft_prec) :: distance
292 INTEGER :: iy, jx
293
294 DO iy = dimy_start, dimy_end
295 DO jx = dimx_start, dimx_end
296 distance= ( iy**2 + (jx-1)**2 )**0.5 + 1.
297 filter(iy,jx) = COMPLEX((1./distance**filterexpo), 0.)
298 END DO
299 END DO
300 filter(:,:) = filter(:,:) /sum(filter(:,:))
301 END SUBROUTINE lowpassfilter
302
303 !==============================================================================
subroutine lowpassfilter(dimy_start, dimy_end, dimx_start, dimx_end, filterexpo, filter)
LowPassFilter
subroutine setdimsforfft(ispec)
SetDimsForFFT
subroutine gft2dconvolution(isp, ny, mx, niy, mjx, spatdatain, kerneltransf, spatdataout)
subroutine gft2dtransformkernel(ny, mx, niy, mjx, y_dim_kernel, x_dim_kernel, kernelin, kerneltransf)
GFT2DTransformKernel
real function distance(x, x0, y, y0)
Distance.
subroutine reorderkernelforgft(dim_y, dim_x, shifted_kernel, reorderedkernel)
ReorderKernelForGFT.
type(specproperties), dimension(maxspc) spec
Definition All_par.f90:345
integer maxlon
Definition All_par.f90:46
integer maxlat
Definition All_par.f90:45
Definition GFT.f90:15