SURFEX v8.1
General documentation of Surfex
hor_interpol_rotlatlon.F90
Go to the documentation of this file.
1 !SFX_LIC Copyright 1994-2014 CNRS, Meteo-France and Universite Paul Sabatier
2 !SFX_LIC This is part of the SURFEX software governed by the CeCILL-C licence
3 !SFX_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
4 !SFX_LIC for details. version 1.
5 ! #########
6 SUBROUTINE hor_interpol_rotlatlon(KLUOUT,PFIELDIN,PFIELDOUT)
7 ! #################################################################################
8 !
9 !!**** *HOR_INTERPOL_ROTLATLON * - Interpolation from a rotated lat/lon grid
10 !!
11 !! PURPOSE
12 !! -------
13 !!
14 !!** METHOD
15 !! ------
16 !!
17 !! REFERENCE
18 !! ---------
19 !!
20 !!
21 !! AUTHOR
22 !! ------
23 !! U. Andrae
24 !!
25 !! MODIFICATIONS
26 !! -------------
27 !! Original 10/2007
28 !!------------------------------------------------------------------
29 !
30 !
31 USE modd_surfex_mpi, ONLY : nrank, npio, ncomm, nproc, idx_i
32 USE modd_prep, ONLY : xlat_out, xlon_out
34 USE modd_surf_par, ONLY : xundef
35 USE modd_grid_grib, ONLY : nni
36 
37 !
38 !
39 USE yomhook ,ONLY : lhook, dr_hook
40 USE parkind1 ,ONLY : jprb
41 !
42 IMPLICIT NONE
43 !
44 #ifdef SFX_MPI
45 include "mpif.h"
46 #endif
47 !
48 !* 0.1 declarations of arguments
49 !
50 INTEGER, INTENT(IN) :: KLUOUT ! logical unit of output listing
51 REAL, DIMENSION(:,:), INTENT(IN) :: PFIELDIN ! field to interpolate horizontally
52 REAL, DIMENSION(:,:), INTENT(OUT) :: PFIELDOUT ! interpolated field
53 !
54 !* 0.2 declarations of local variables
55 !
56 #ifdef SFX_MPI
57 INTEGER, DIMENSION(MPI_STATUS_SIZE) :: ISTATUS
58 #endif
59 REAL, DIMENSION(:,:,:), ALLOCATABLE :: ZW, ZFIELDIN,ZFGET
60 INTEGER, DIMENSION(:,:,:), ALLOCATABLE :: IJD,IJGET
61 REAL, DIMENSION(:), ALLOCATABLE :: XLAT_IND, XLON_IND, XRAT_OUT, XRON_OUT
62 !
63 INTEGER :: INFOMPI
64 INTEGER :: J, I, JI, INO, JL, INL, ILON, ILAT, ISIZE
65 REAL :: ZWX, ZWY, ZWSUM
66 !
67 REAL(KIND=JPRB) :: ZHOOK_HANDLE
68 !
69 !-------------------------------------------------------------------------------------
70 IF (lhook) CALL dr_hook('HOR_INTERPOL_ROTLATLON',0,zhook_handle)
71 !
72 WRITE(kluout,'(A)')' | Running rotated latlon interpolation'
73 !
74 ino = SIZE(xlat_out)
75 inl = SIZE(pfieldout,2)
76 !
77 !
78 !* 1. Allocations
79 !
80 ALLOCATE(xrat_out(ino),xron_out(ino),xlat_ind(ino),xlon_ind(ino),ijd(ino,inl,4),zw(ino,inl,4))
81 !
82 !* Transformation of latitudes/longitudes into rotated coordinates
83 !
84  CALL regrot(xlon_out,xlat_out,xron_out,xrat_out,xrlop,xrlap,1)
85 !
86 DO j=1,ino
87  xlat_ind(j) = ( xrat_out(j) - xrila1) / xrdy + 1.
88  xlon_ind(j) = ( xron_out(j) - xrilo1) / xrdx + 1.
89 ENDDO
90 !
91 pfieldout(:,:) = xundef
92 !
93 zw(:,:,:) = 0.
94 DO jl=1,inl
95  !
96  DO ji=1,ino
97  !
98  ilon = int(xlon_ind(ji))
99  ilat = int(xlat_ind(ji))
100  !
101  zwx = xlon_ind(ji) - float(ilon)
102  zwy = xlat_ind(ji) - float(ilat)
103  !
104  zw(ji,jl,1) = (1.-zwx)*(1.-zwy)
105  zw(ji,jl,2) = (1.-zwx)* zwy
106  zw(ji,jl,3) = zwx *(1.-zwy)
107  zw(ji,jl,4) = zwx * zwy
108  !
109  ijd(ji,jl,1) = ilon + nrx*(ilat -1)
110  ijd(ji,jl,2) = ilon + nrx*(ilat+1 -1)
111  ijd(ji,jl,3) = ilon+1 + nrx*(ilat -1)
112  ijd(ji,jl,4) = ilon+1 + nrx*(ilat+1 -1)
113  !
114  ENDDO
115  !
116 ENDDO
117 !
118 ALLOCATE(zfieldin(ino,inl,4))
119 !
120 IF (nrank/=npio) THEN
121  !
122  idx_i = idx_i + 1
123 #ifdef SFX_MPI
124  CALL mpi_send(ino,kind(ino)/4,mpi_integer,npio,idx_i,ncomm,infompi)
125 #endif
126  !
127  idx_i = idx_i + 1
128 #ifdef SFX_MPI
129  CALL mpi_send(ijd,SIZE(ijd)*kind(ijd)/4,mpi_integer,npio,idx_i,ncomm,infompi)
130 #endif
131  !
132  idx_i = idx_i + 1
133 #ifdef SFX_MPI
134  CALL mpi_recv(zfieldin,SIZE(zfieldin)*kind(zfieldin)/4,mpi_real,npio,idx_i,ncomm,istatus,infompi)
135 #endif
136  !
137 ELSE
138  !
139  DO j=0,nproc-1
140  !
141  IF (j/=npio) THEN
142 #ifdef SFX_MPI
143  CALL mpi_recv(isize,kind(isize)/4,mpi_integer,j,idx_i+1,ncomm,istatus,infompi)
144 #endif
145  ALLOCATE(ijget(isize,inl,4))
146 #ifdef SFX_MPI
147  CALL mpi_recv(ijget,SIZE(ijget)*kind(ijget)/4,mpi_integer,j,idx_i+2,ncomm,istatus,infompi)
148 #endif
149  ELSE
150  isize = ino
151  ALLOCATE(ijget(isize,inl,4))
152  ijget(:,:,:) = ijd(:,:,:)
153  ENDIF
154  !
155  ALLOCATE(zfget(isize,inl,4))
156  !
157  zfget(:,:,:) = 0.
158  DO jl = 1,inl
159  DO ji = 1,isize
160  DO i = 1,4
161  zfget(ji,jl,i) = pfieldin(ijget(ji,jl,i),jl)
162  ENDDO
163  ENDDO
164  ENDDO
165  !
166  IF (j/=npio) THEN
167 #ifdef SFX_MPI
168  CALL mpi_send(zfget,SIZE(zfget)*kind(zfget)/4,mpi_real,j,idx_i+3,ncomm,infompi)
169 #endif
170  ELSE
171  zfieldin(:,:,:) = zfget(:,:,:)
172  ENDIF
173  !
174  DEALLOCATE(ijget,zfget)
175  !
176  ENDDO
177  !
178  idx_i = idx_i + 3
179  !
180 ENDIF
181 !
182 DO jl = 1,inl
183  DO ji = 1,ino
184  !
185  DO i = 1,4
186  IF (abs(zfieldin(ji,jl,i)-xundef)<1.e-6) zw(ji,jl,i) = 0.
187  ENDDO
188  !
189  zwsum = zw(ji,jl,1) + zw(ji,jl,2) + zw(ji,jl,3) + zw(ji,jl,4)
190  !
191  IF ( abs(zwsum)<1.e-6 ) THEN
192  zw(ji,jl,1) = 1.
193  ELSE
194  DO i = 1,4
195  zw(ji,jl,i) = zw(ji,jl,i)/zwsum
196  ENDDO
197  ENDIF
198  !
199  pfieldout(ji,jl) = zw(ji,jl,1)*zfieldin(ji,jl,1) + zw(ji,jl,2)*zfieldin(ji,jl,2) + &
200  zw(ji,jl,3)*zfieldin(ji,jl,3) + zw(ji,jl,4)*zfieldin(ji,jl,4)
201  !
202  ENDDO
203 ENDDO
204 !
205 !* 5. Deallocations
206 DEALLOCATE(xrat_out,xron_out,xlat_ind,xlon_ind,ijd,zfieldin)
207 !
208 IF (lhook) CALL dr_hook('HOR_INTERPOL_ROTLATLON',1,zhook_handle)
209 !
210 CONTAINS
211 !
212 SUBROUTINE regrot(PXREG,PYREG,PXROT,PYROT,PXCEN,PYCEN,KCALL)
213 !
214 USE modd_csts, ONLY : xpi
215 !
216 USE modi_abor1_sfx
217 !
218 IMPLICIT NONE
219 !
220 !-----------------------------------------------------------------------
221 !
222 !* CONVERSION BETWEEN REGULAR AND ROTATED SPHERICAL COORDINATES.
223 !*
224 !* PXREG LONGITUDES OF THE REGULAR COORDINATES
225 !* PYREG LATITUDES OF THE REGULAR COORDINATES
226 !* PXROT LONGITUDES OF THE ROTATED COORDINATES
227 !* PYROT LATITUDES OF THE ROTATED COORDINATES
228 !* ALL COORDINATES GIVEN IN DEGREES N (NEGATIVE FOR S)
229 !* AND DEGREES E (NEGATIVE VALUES FOR W)
230 !* KXDIM DIMENSION OF THE GRIDPOINT FIELDS IN THE X-DIRECTION
231 !* KYDIM DIMENSION OF THE GRIDPOINT FIELDS IN THE Y-DIRECTION
232 !* KX NUMBER OF GRIDPOINT IN THE X-DIRECTION
233 !* KY NUMBER OF GRIDPOINTS IN THE Y-DIRECTION
234 !* PXCEN REGULAR LONGITUDE OF THE SOUTH POLE OF THE ROTATED GRID
235 !* PYCEN REGULAR LATITUDE OF THE SOUTH POLE OF THE ROTATED GRID
236 !*
237 !* KCALL=-1: FIND REGULAR AS FUNCTIONS OF ROTATED COORDINATES.
238 !* KCALL= 1: FIND ROTATED AS FUNCTIONS OF REGULAR COORDINATES.
239 !*
240 !* J.E. HAUGEN HIRLAM JUNE -92
241 !
242 !-----------------------------------------------------------------------
243 !
244 INTEGER, INTENT(IN) :: KCALL
245 REAL, INTENT(IN) :: PXCEN,PYCEN
246 REAL, DIMENSION(:), INTENT(INOUT) :: PXREG, PYREG
247 REAL, DIMENSION(:), INTENT(INOUT) :: PXROT, PYROT
248 !
249 !-----------------------------------------------------------------------
250 !
251 REAL :: ZRAD,ZSYCEN,ZCYCEN,ZXMXC,ZSXMXC,ZCXMXC,ZSYREG,ZCYREG, &
252  ZSYROT,ZCYROT,ZCXROT,ZSXROT,ZRADI
253 INTEGER :: JI, ISIZE
254 REAL(KIND=JPRB) :: ZHOOK_HANDLE
255 !
256 !-----------------------------------------------------------------------
257 !
258 IF (lhook) CALL dr_hook('REGROT',0,zhook_handle)
259 !
260 isize = SIZE(pxreg)
261 !
262 zrad = xpi/180.
263 zradi = 1./zrad
264 zsycen = sin(zrad*(pycen+90.))
265 zcycen = cos(zrad*(pycen+90.))
266 !
267 IF (kcall.EQ.1) THEN
268  !
269  DO ji = 1,isize
270  !
271  zxmxc = zrad*(pxreg(ji) - pxcen)
272  zsxmxc = sin(zxmxc)
273  zcxmxc = cos(zxmxc)
274  !
275  zsyreg = sin(zrad*pyreg(ji))
276  zcyreg = cos(zrad*pyreg(ji))
277  !
278  zsyrot = zcycen*zsyreg - zsycen*zcyreg*zcxmxc
279  zsyrot = min(max(zsyrot,-1.0),+1.0)
280  !
281  pyrot(ji) = asin(zsyrot)*zradi
282  !
283  zcyrot = cos(zrad*pyrot(ji))
284  zcxrot = (zcycen*zcyreg*zcxmxc + zsycen*zsyreg)/zcyrot
285  zcxrot = min(max(zcxrot,-1.0),+1.0)
286  zsxrot = zcyreg*zsxmxc/zcyrot
287  !
288  pxrot(ji) = acos(zcxrot)*zradi
289  !
290  IF (zsxrot.LT.0.0) pxrot(ji) = -pxrot(ji)
291  !
292  ENDDO
293  !
294 ELSEIF (kcall.EQ.-1) THEN
295  !
296  DO ji = 1,isize
297  !
298  zsxrot = sin(zrad*pxrot(ji))
299  zcxrot = cos(zrad*pxrot(ji))
300  zsyrot = sin(zrad*pyrot(ji))
301  zcyrot = cos(zrad*pyrot(ji))
302  !
303  zsyreg = zcycen*zsyrot + zsycen*zcyrot*zcxrot
304  zsyreg = max(zsyreg,-1.0)
305  zsyreg = min(zsyreg,+1.0)
306  !
307  pyreg(ji) = asin(zsyreg)*zradi
308  !
309  zcyreg = cos(pyreg(ji)*zrad)
310  !
311  zcxmxc = (zcycen*zcyrot*zcxrot - zsycen*zsyrot)/zcyreg
312  zcxmxc = max(zcxmxc,-1.0)
313  zcxmxc = min(zcxmxc,+1.0)
314  zsxmxc = zcyrot*zsxrot/zcyreg
315  zxmxc = acos(zcxmxc)*zradi
316  IF (zsxmxc.LT.0.0) zxmxc = -zxmxc
317  !
318  pxreg(ji) = zxmxc + pxcen
319  !
320  ENDDO
321  !
322 ELSE
323  !
324  WRITE(6,'(1X,''INVALID KCALL IN REGROT'')')
325  CALL abor1_sfx('HOR_INTERPOL_ROTLATON:REGROT:KCALL MUST BE 1 OR -1')
326  !
327 ENDIF
328 !
329 IF (lhook) CALL dr_hook('REGROT',1,zhook_handle)
330 !
331 END SUBROUTINE regrot
332 !
333 !-------------------------------------------------------------------------------------
334 END SUBROUTINE hor_interpol_rotlatlon
subroutine regrot(PXREG, PYREG, PXROT, PYROT, PXCEN, PYCEN, KCALL)
real, dimension(:), allocatable xlon_out
Definition: modd_prep.F90:48
real, save xpi
Definition: modd_csts.F90:43
subroutine abor1_sfx(YTEXT)
Definition: abor1_sfx.F90:7
real, parameter xundef
integer, parameter jprb
Definition: parkind1.F90:32
real, dimension(:), allocatable xlat_out
Definition: modd_prep.F90:47
logical lhook
Definition: yomhook.F90:15
subroutine hor_interpol_rotlatlon(KLUOUT, PFIELDIN, PFIELDOUT)