SURFEX v8.1
General documentation of Surfex
get_mesh_index_gauss.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 get_mesh_index_gauss(KNBLINES,KSSO,PGRID_PAR,PLAT,PLON,&
7  KINDEX,KISSOX,KISSOY,PVALUE,PNODATA)
8 ! ###############################################################
9 !
10 !!**** *GET_MESH_INDEX_GAUSS* get the grid mesh where point (lat,lon) is located
11 !!
12 !! PURPOSE
13 !! -------
14 !!
15 !! AUTHOR
16 !! ------
17 !!
18 !! V. Masson Meteo-France
19 !!
20 !! MODIFICATION
21 !! ------------
22 !!
23 !! Original 12/09/95
24 !!
25 !----------------------------------------------------------------------------
26 !
27 !* 0. DECLARATION
28 ! -----------
29 !
30 USE eggangles,ONLY : lola, angle_domain
31 !
35  xlatp, xcosp, xsinp, xpi, x1, x2, xdr, &
38 !
40 !
41 USE yomhook ,ONLY : lhook, dr_hook
42 USE parkind1 ,ONLY : jprb
43 !
44 IMPLICIT NONE
45 !
46 !* 0.1 Declaration of arguments
47 ! ------------------------
48 !
49 INTEGER, INTENT(IN) :: KNBLINES
50 INTEGER, INTENT(IN) :: KSSO ! number of subgrid mesh in each direction
51 REAL, DIMENSION(:), INTENT(IN) :: PGRID_PAR ! grid parameters
52 REAL, DIMENSION(:), INTENT(IN) :: PLAT ! latitude of the point (degrees)
53 REAL, DIMENSION(:), INTENT(IN) :: PLON ! longitude of the point (degrees)
54 INTEGER, DIMENSION(:,:), INTENT(OUT) :: KINDEX ! index of the grid mesh where the point is
55 INTEGER, DIMENSION(:,:), INTENT(OUT) :: KISSOX ! X index of the subgrid mesh
56 INTEGER, DIMENSION(:,:), INTENT(OUT) :: KISSOY ! Y index of the subgrid mesh
57 !
58 REAL, DIMENSION(:), OPTIONAL, INTENT(IN) :: PVALUE ! value of the point to add
59 REAL, OPTIONAL, INTENT(IN) :: PNODATA
60 
61 !
62 !* 0.2 Declaration of other local variables
63 ! ------------------------------------
64 !
65 REAL, DIMENSION(SIZE(PLAT)) :: ZX, ZY ! pseudo longitude of input point
66 REAL, DIMENSION(SIZE(PLAT)) :: ZVALUE
67 REAL :: ZPC2
68 REAL :: ZNODATA
69 !
70 INTEGER, DIMENSION(SIZE(PLAT)) :: ICJ
71 INTEGER :: ILGRID, ISIZE_LON, ISIZE_DLAT, INBLINES ! number of grid points
72 INTEGER :: IFACTX, ISIZEX, ISIZEY
73 INTEGER :: JI, JJ, JL ! loop counter in x
74 INTEGER :: JGRID, IGRID0 ! loop counter on grid points
75 !
76 REAL(KIND=JPRB) :: ZHOOK_HANDLE, ZHOOK_HANDLE_OMP
77 !----------------------------------------------------------------------------
78 !
79 IF (lhook) CALL dr_hook('GET_MESH_INDEX_GAUSS_1',0,zhook_handle)
80 !
81 IF (PRESENT(pvalue) .AND. PRESENT(pnodata)) THEN
82  zvalue(:) = pvalue(:)
83  znodata = pnodata
84 ELSE
85  zvalue(:) = 1
86  znodata = 0
87 ENDIF
88 !
89 kindex(:,:) = 0
90 kissox(:,:) = 0
91 kissoy(:,:) = 0
92 !
93 IF (.NOT. ALLOCATED(nnlopa)) THEN
94  !
95  !* 1. Gets parameters of the projection
96  ! ---------------------------------
97  !
98  xpi = 4.*atan(1.)
99  xdr = xpi / 180.
100  !
101  CALL get_gridtype_gauss(pgrid_par,nnlati,kl=ilgrid)
102  !
103  ALLOCATE(nnlopa(0:nnlati))
104  ALLOCATE(xxcen(ilgrid))
105  ALLOCATE(xycen(ilgrid))
107  ilgrid,plat_xy=xycen,plon_xy=xxcen )
108  nnlopa(0) = 0
109  !
110  zpc2 = xcodil*xcodil
111  x1 = 1.0-zpc2
112  x2 = 1.0+zpc2
113  !
114  xlonp = angle_domain(xlopo,dom='0+',unit='D') * xdr
115  xlatp = xlapo * xdr
116  !
117  xcosp = cos(xlatp)
118  xsinp = sin(xlatp)
119  !
120  !* 2. Limits of grid meshes in x and y
121  ! --------------------------------
122  !
123  ALLOCATE(xxinf(ilgrid))
124  ALLOCATE(xyinf(ilgrid))
125  ALLOCATE(xxsup(ilgrid))
126  ALLOCATE(xysup(ilgrid))
127  ALLOCATE(xxdif(ilgrid))
128  ALLOCATE(xydif(ilgrid))
129  !
131  DO jj=1,ilgrid
132  xxdif(jj) = 1. / (xxsup(jj) - xxinf(jj))
133  xydif(jj) = 1. / (xysup(jj) - xyinf(jj))
134  ENDDO
135  !
136  ifactx = floor(sqrt(float(nnlati))) + 1
137  isizex = floor(float(nnlati) / ifactx)
138  !
139  ALLOCATE(nfracdx(0:ifactx))
140  ALLOCATE(nfracgx(0:ifactx))
141  !
142  nfracdx(0) = 0
143  nfracgx(0) = 1
144  nfracdx(1) = 1
145  nfracgx(1) = 1
146  nfracdx(ifactx) = nnlati
147  nfracgx(ifactx) = sum(nnlopa(:))
148  DO jj=2,ifactx-1
149  nfracdx(jj) = 1 + (jj-1) * isizex
150  nfracgx(jj) = nfracgx(jj-1) + sum(nnlopa(nfracdx(jj-1):(jj-1)*isizex))
151  ENDDO
152  !
153  !
154  ALLOCATE(nfacty(nnlati))
155  nfacty(:) = floor(sqrt(float(nnlopa(1:nnlati))))+1
156  !
157  ALLOCATE(nfracdy(nnlati,0:maxval(nfacty)))
158  !
159  DO jj=1,nnlati
160  isizey = floor(float(nnlopa(jj)) / nfacty(jj))
161  nfracdy(jj,0) = 0
162  nfracdy(jj,1) = 1
163  nfracdy(jj,nfacty(jj)) = nnlopa(jj)
164  DO ji=2,nfacty(jj)-1
165  nfracdy(jj,ji) = 1 + (ji-1) * isizey
166  ENDDO
167  ENDDO
168  !
169  !* 3. Find if rotated pole and/or stretching to improve CPU time
170  ! ----------------------------------------------------------
171  !
172  lrotstretch = .true.
173  IF (xcodil==1.0.AND.xlapo==90.0.AND.xlopo==0.0) lrotstretch = .false.
174  !
175 ENDIF
176 !
177 ! case where the grid is not regular: all points are considered independently
178 IF (knblines==0) THEN
179  inblines = SIZE(plat)
180 ELSE
181  inblines = knblines
182 ENDIF
183 !
184 isize_dlat = SIZE(plat)/inblines
185 !
186 ! case where the grid is not regular: all points are considered independently
187 IF (knblines==0) THEN
188  isize_lon = inblines
189 ELSE
190  isize_lon = isize_dlat
191 ENDIF
192 !
193 IF (ALLOCATED(xlon)) THEN
194  IF ( isize_lon/=SIZE(xlon) .OR. inblines/=SIZE(xlat) ) THEN
195  DEALLOCATE(xlon)
196  DEALLOCATE(xlat)
197  DEALLOCATE(xcost)
198  DEALLOCATE(xsintc)
199  DEALLOCATE(xsints)
200  DEALLOCATE(xcosn)
201  DEALLOCATE(xsinn)
202  ENDIF
203 ENDIF
204 !
205 IF (.NOT.ALLOCATED(xlon)) THEN
206  !
207  ALLOCATE(xlon(isize_lon))
208  ALLOCATE(xlat(inblines))
209  !
210  ALLOCATE(xcost(SIZE(xlat)))
211  ALLOCATE(xsintc(SIZE(xlat)))
212  ALLOCATE(xsints(SIZE(xlat)))
213  ALLOCATE(xcosn(SIZE(xlon)))
214  ALLOCATE(xsinn(SIZE(xlon)))
215  !
216  xlon(:) = angle_domain(plon(1:isize_lon),dom='0+',unit='D') * xdr
217  xcosn(:) = cos(xlon(:)-xlonp)
218  xsinn(:) = sin(xlon(:)-xlonp)
219  !
220 ENDIF
221 !
222 IF (lhook) CALL dr_hook('GET_MESH_INDEX_GAUSS_1',1,zhook_handle)
223 IF (lhook) CALL dr_hook('GET_MESH_INDEX_GAUSS_2',0,zhook_handle)
224 
225 !
226 !* 3. Projection of input points into pseudo coordinates
227 ! --------------------------------------------------
228 !
229 DO jj=1,inblines
230  xlat(jj) = plat(jj*isize_dlat) * xdr
231  xsintc(jj) = sin(xlat(jj)) * xcosp
232  xsints(jj) = sin(xlat(jj)) * xsinp
233  xcost(jj) = cos(xlat(jj))
234 ENDDO
235 !
236 IF (lrotstretch) THEN
237  CALL xy_gauss(xcodil,isize_dlat,isize_lon,znodata,zvalue,zy,zx)
238 ELSE
239  zx(:) = plon(:)
240  zy(:) = plat(:)
241 ENDIF
242 !
243 !-------------------------------------------------------------------------------
244 !
245 !* 5. Localisation of the data points on (x,y) grid
246 ! ---------------------------------------------
247 !
248 icj(:) = 0
249 !
250 ifactx = SIZE(nfracdx)
251 !
252 IF (lhook) CALL dr_hook('GET_MESH_INDEX_GAUSS_2',1,zhook_handle)
253 !
254 !$OMP PARALLEL PRIVATE(ZHOOK_HANDLE_OMP)
255 IF (lhook) CALL dr_hook('GET_MESH_INDEX_GAUSS_3',0,zhook_handle_omp)
256 !$OMP DO PRIVATE(JJ,JI,JGRID)
257 DO jl=1,SIZE(plat)
258  !
259  IF (zvalue(jl)==znodata) cycle
260  !
261  fracx: &
262  DO jj=1,ifactx
263  !
264  IF (zy(jl)>=xyinf(nfracgx(jj))) THEN
265  !
266  jgrid = nfracgx(jj-1)
267  !
268  DO ji=nfracdx(jj-1)+1,nfracdx(jj)-1
269  !
270  jgrid = jgrid + nnlopa(ji-1)
271  !
272  IF (zy(jl)>=xyinf(jgrid)) THEN
273  !
274  icj(jl) = ji
275  EXIT fracx
276  !
277  ENDIF
278  !
279  ENDDO
280  !
281  icj(jl) = nfracdx(jj)
282  !
283  exit fracx
284  !
285  ENDIF
286  !
287  ENDDO fracx
288  !
289 ENDDO
290 !$OMP END DO
291 IF (lhook) CALL dr_hook('GET_MESH_INDEX_GAUSS_3',1,zhook_handle_omp)
292 !$OMP END PARALLEL
293 !
294 !
295 !$OMP PARALLEL PRIVATE(ZHOOK_HANDLE_OMP)
296 IF (lhook) CALL dr_hook('GET_MESH_INDEX_GAUSS_4',0,zhook_handle_omp)
297 !$OMP DO PRIVATE(IGRID0,JGRID,JI,JJ)
298 DO jl=1,SIZE(plat)
299  !
300  IF (zvalue(jl)==znodata) cycle
301  !
302  igrid0 = 0
303  IF (icj(jl)/=1) igrid0 = sum(nnlopa(1:icj(jl)-1))
304  !
305  !* loop on grid points: longitude
306  fracy: &
307  DO jj = 1,nfacty(icj(jl))
308  !
309  IF (zx(jl)<xxsup(igrid0+nfracdy(icj(jl),jj))) THEN
310  !
311  jgrid = igrid0 + nfracdy(icj(jl),jj-1)
312  !
313  DO ji=nfracdy(icj(jl),jj-1)+1,nfracdy(icj(jl),jj)
314  !
315  jgrid = jgrid + 1
316  IF (zx(jl)<=xxcen(jgrid)-180. .AND. zx(jl)<xxsup(jgrid)-360.) zx(jl) = zx(jl) + 360.
317  !* imput point is in this grid mesh
318  IF (zx(jl)>=xxinf(jgrid) .AND. zx(jl)<xxsup(jgrid)) THEN
319  !
320  kindex(1,jl) = jgrid
321  !
322  EXIT fracy
323  !
324  ENDIF
325  !
326  ENDDO
327  !
328  END IF
329  !
330  END DO fracy
331  !
332 END DO
333 !£$OMP END DO
334 IF (lhook) CALL dr_hook('GET_MESH_INDEX_GAUSS_4',1,zhook_handle_omp)
335 !$OMP END PARALLEL
336 !
337 !
338 !* 6. Localisation of the data points on in the subgrid of this mesh
339 ! --------------------------------------------------------------
340 !
341 IF (ksso/=0) THEN
342 !$OMP PARALLEL PRIVATE(ZHOOK_HANDLE_OMP)
343 IF (lhook) CALL dr_hook('GET_MESH_INDEX_GAUSS_5',0,zhook_handle_omp)
344 !$OMP DO
345  DO jl=1,SIZE(plat)
346  IF (kindex(1,jl)/=0) THEN
347  kissox(1,jl) = 1 + int( float(ksso) * (zx(jl)-xxinf(kindex(1,jl)))/(xxsup(kindex(1,jl))-xxinf(kindex(1,jl))) )
348  kissoy(1,jl) = 1 + int( float(ksso) * (zy(jl)-xyinf(kindex(1,jl)))/(xysup(kindex(1,jl))-xyinf(kindex(1,jl))) )
349  ENDIF
350  ENDDO
351 !$OMP END DO
352 IF (lhook) CALL dr_hook('GET_MESH_INDEX_GAUSS_5',1,zhook_handle_omp)
353 !$OMP END PARALLEL
354 ENDIF
355 !
356 !-------------------------------------------------------------------------------
357 !
358 END SUBROUTINE get_mesh_index_gauss
real, dimension(:), allocatable xsinn
subroutine gauss_grid_limits(KNLATI, KNLOPA, PXINF, PXSUP, PYINF, PYSUP)
real, dimension(:), allocatable xxinf
real, dimension(:), allocatable xxcen
real, dimension(:), allocatable xysup
real, dimension(:), allocatable xlon
real, dimension(:), allocatable xycen
real, dimension(:), allocatable xsintc
real, dimension(:), allocatable xydif
subroutine xy_gauss(PCODIL, KSIZE_DLAT, KSIZE_LON, PNODATA, PVALUE, PLAT_XY, PLON_XY)
subroutine get_mesh_index_gauss(KNBLINES, KSSO, PGRID_PAR, PLAT, PLON,
integer, parameter jprb
Definition: parkind1.F90:32
integer, dimension(:), allocatable nfacty
real, dimension(:), allocatable xyinf
integer, dimension(:,:), allocatable nfracdy
real, dimension(:), allocatable xxsup
integer, dimension(:), allocatable nfracgx
real, dimension(:), allocatable xcosn
intent(out) overrides sub arrays one Sort by the least significant key first sum(iindex(1:n))
logical lhook
Definition: yomhook.F90:15
subroutine get_gridtype_gauss(PGRID_PAR, KNLATI, PLAPO, PLOPO, PCODIL, KNLOPA, KL, PLAT, PLON, PLAT_XY, PLON_XY, PMESH_SIZE, PLONINF, PLATINF, PLONSUP, PLATSUP)
integer, dimension(:), allocatable nfracdx
real, dimension(:), allocatable xsints
integer, dimension(:), allocatable nnlopa
real, dimension(:), allocatable xxdif
real, dimension(:), allocatable xlat
real, dimension(:), allocatable xcost