SURFEX  V8_0
Surfex V8_0 release
 All Classes Files Functions Variables
get_near_meshes_ign.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_near_meshes_ign(KGRID_PAR,KL,PGRID_PAR,KNEAR_NBR,KNEAR)
7 ! ##############################################################
8 !
9 !!**** *GET_NEAR_MESHES_IGN* get the near grid mesh indices
10 !!
11 !! PURPOSE
12 !! -------
13 !!
14 !! METHOD
15 !! ------
16 !!
17 !! REFERENCE
18 !! ---------
19 !!
20 !! AUTHOR
21 !! ------
22 !!
23 !! V. Masson Meteo-France
24 !!
25 !! MODIFICATION
26 !! ------------
27 !!
28 !! Original 03/2004
29 !!
30 !
31 ! Modifié par Renaud Lestrigant (02/2016) : changement complet de l'algo
32 ! de recherche des plus proches voisins.
33 ! Récupération d'un code sur Internet et adaptation locale.
34 ! (http://jblevins.org/mirror/amiller/qsort.f90)
35 !
36 !----------------------------------------------------------------------------
37 !
38 !* 0. DECLARATION
39 ! -----------
40 !
42 !
43 USE yomhook ,ONLY : lhook, dr_hook
44 USE parkind1 ,ONLY : jprb
45 !
46 IMPLICIT NONE
47 !
48 !* 0.1 Declaration of arguments
49 ! ------------------------
50 !
51 INTEGER, INTENT(IN) :: kgrid_par ! size of PGRID_PAR
52 INTEGER, INTENT(IN) :: kl ! number of points
53 INTEGER, INTENT(IN) :: knear_nbr ! number of nearest points wanted
54 REAL, DIMENSION(KGRID_PAR), INTENT(IN) :: pgrid_par ! grid parameters
55 INTEGER, DIMENSION(:,:),POINTER :: knear ! near mesh indices
56 !
57 !* 0.2 Declaration of other local variables
58 ! ------------------------------------
59 !
60 REAL,DIMENSION(KL) :: zx
61 REAL,DIMENSION(KL) :: zy
62 REAL,DIMENSION(KL) :: zdx
63 REAL,DIMENSION(KL) :: zdy
64 REAL,DIMENSION(KL) :: zdis
65 INTEGER,DIMENSION(KL) :: indzdis
66 
67 REAL :: zmaxvaldis
68 
69 INTEGER :: isize, jp
70 REAL(KIND=JPRB) :: zhook_handle
71 !
72 !----------------------------------------------------------------------------
73 !
74 IF (lhook) CALL dr_hook('GET_NEAR_MESHES_IGN_1',0,zhook_handle)
75 !
76  CALL get_gridtype_ign(pgrid_par,px=zx,py=zy,pdx=zdx,pdy=zdy)
77 !
78 knear(:,:) = 0
79 !
80 isize = min(knear_nbr,kl)
81 !
82 ! calcul de la distance de tous les points 2 à 2
83 !
84 !
85 IF (lhook) CALL dr_hook('GET_NEAR_MESHES_IGN_1',1,zhook_handle)
86 IF (lhook) CALL dr_hook('GET_NEAR_MESHES_IGN_2',0,zhook_handle)
87 !
88 !$OMP PARALLEL DO PRIVATE(JP,ZDIS,ZMAXVALDIS,INDZDIS)
89 !
90 DO jp=1,kl
91  !
92  ! distance du point JP à tous les autres points
93  zdis(:) = sqrt((zx(:)-zx(jp))**2 + (zy(:)-zy(jp))**2)
94  ! distance maximale entre JP et les autres moints
95  zmaxvaldis = 2. * maxval(zdis)
96  zdis(jp) = zmaxvaldis
97 
98  CALL quick_sort(zdis, indzdis)
99  knear(jp,1:isize) = indzdis(1:isize)
100  !
101 ENDDO
102 !$OMP END PARALLEL DO
103 !
104 IF (lhook) CALL dr_hook('GET_NEAR_MESHES_IGN_2',1,zhook_handle)
105 !
106  CONTAINS
107 !
108 RECURSIVE SUBROUTINE quick_sort(PLIST, KORDER)
109 
110 ! Quick sort routine from:
111 ! Brainerd, W.S., Goldberg, C.H. & Adams, J.C. (1990) "Programmer's Guide to
112 ! Fortran 90", McGraw-Hill ISBN 0-07-000248-7, pages 149-150.
113 ! Modified by Alan Miller to include an associated integer array which gives
114 ! the positions of the elements in the original order.
115 !
116 IMPLICIT NONE
117 !
118 REAL, DIMENSION (:), INTENT(INOUT) :: plist
119 INTEGER, DIMENSION (:), INTENT(OUT) :: korder
120 !
121 ! Local variable
122 INTEGER :: ji
123 
124 DO ji = 1, SIZE(plist)
125  korder(ji) = ji
126 END DO
127 
128  CALL quick_sort_1(1, SIZE(plist), plist, korder)
129 
130 END SUBROUTINE quick_sort
131 
132 
133 RECURSIVE SUBROUTINE quick_sort_1(KLEFT_END, KRIGHT_END, PLIST1, KORDER1)
134 
135 INTEGER, INTENT(IN) :: kleft_end, kright_end
136 REAL, DIMENSION (:), INTENT(INOUT) :: plist1
137 INTEGER, DIMENSION (:), INTENT(INOUT) :: korder1
138 ! Local variables
139 INTEGER :: ji, jj, itemp
140 REAL :: zref, ztemp
141 INTEGER, PARAMETER :: imax_simple_sort_size = 6
142 
143 IF (kright_end < kleft_end + imax_simple_sort_size) THEN
144  ! Use interchange sort for small PLISTs
145  CALL interchange_sort(kleft_end, kright_end, plist1, korder1)
146  !
147 ELSE
148  !
149  ! Use partition ("quick") sort
150  ! valeur au centre du tableau
151  zref = plist1((kleft_end + kright_end)/2)
152  ji = kleft_end - 1
153  jj = kright_end + 1
154 
155  DO
156  ! Scan PLIST from left end until element >= ZREF is found
157  DO
158  ji = ji + 1
159  IF (plist1(ji) >= zref) EXIT
160  END DO
161  ! Scan PLIST from right end until element <= ZREF is found
162  DO
163  jj = jj - 1
164  IF (plist1(jj) <= zref) EXIT
165  END DO
166 
167 
168  IF (ji < jj) THEN
169  ! Swap two out-of-order elements
170  ztemp = plist1(ji)
171  plist1(ji) = plist1(jj)
172  plist1(jj) = ztemp
173  itemp = korder1(ji)
174  korder1(ji) = korder1(jj)
175  korder1(jj) = itemp
176  ELSE IF (ji == jj) THEN
177  ji = ji + 1
178  EXIT
179  ELSE
180  EXIT
181  END IF
182  END DO
183 
184  IF (kleft_end < jj) CALL quick_sort_1(kleft_end, jj, plist1, korder1)
185  IF (ji < kright_end) CALL quick_sort_1(ji, kright_end,plist1,korder1)
186 END IF
187 
188 END SUBROUTINE quick_sort_1
189 
190 
191 SUBROUTINE interchange_sort(KLEFT_END, KRIGHT_END, PLIST2, KORDER2)
192 
193 INTEGER, INTENT(IN) :: kleft_end, kright_end
194 REAL, DIMENSION (:), INTENT(INOUT) :: plist2
195 INTEGER, DIMENSION (:), INTENT(INOUT) :: korder2
196 ! Local variables
197 INTEGER :: ji, jj, itemp
198 REAL :: ztemp
199 
200 ! boucle sur tous les points
201 DO ji = kleft_end, kright_end - 1
202  !
203  ! boucle sur les points suivants le point JI
204  DO jj = ji+1, kright_end
205  !
206  ! si la distance de JI au point est plus grande que celle de JJ
207  IF (plist2(ji) > plist2(jj)) THEN
208  ! distance de JI au point (la plus grande)
209  ztemp = plist2(ji)
210  ! le point JJ est déplacé à l'indice JI dans le tableau
211  plist2(ji) = plist2(jj)
212  ! le point JI est déplacé à l'indice JJ dans le tableau
213  plist2(jj) = ztemp
214  ! indice du point JI dans le tableau
215  itemp = korder2(ji)
216  ! l'indice du point JJ est mis à la place JI
217  korder2(ji) = korder2(jj)
218  ! l'indice du point JI est mis à la place JJ
219  korder2(jj) = itemp
220  END IF
221  !
222  END DO
223  !
224 END DO
225 
226 END SUBROUTINE interchange_sort
227 !
228 !-------------------------------------------------------------------------------
229 !
230 END SUBROUTINE get_near_meshes_ign
recursive subroutine quick_sort_1(KLEFT_END, KRIGHT_END, PLIST1, KORDER1)
subroutine get_gridtype_ign(PGRID_PAR, KLAMBERT, KL, PX, PY, PDX, PDY, KDIMX, KDIMY, PXALL, PYALL)
recursive subroutine quick_sort(PLIST, KORDER)
subroutine get_near_meshes_ign(KGRID_PAR, KL, PGRID_PAR, KNEAR_NBR, KNEAR)
subroutine interchange_sort(KLEFT_END, KRIGHT_END, PLIST2, KORDER2)