SURFEX v8.1
General documentation of Surfex
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 !
41 USE modd_surfex_mpi, ONLY : nindex, nrank, nnum
43 !
44 USE yomhook ,ONLY : lhook, dr_hook
45 USE parkind1 ,ONLY : jprb
46 !
47 IMPLICIT NONE
48 !
49 !* 0.1 Declaration of arguments
50 ! ------------------------
51 !
52 INTEGER, INTENT(IN) :: KGRID_PAR ! size of PGRID_PAR
53 INTEGER, INTENT(IN) :: KL ! number of points
54 INTEGER, INTENT(IN) :: KNEAR_NBR ! number of nearest points wanted
55 REAL, DIMENSION(KGRID_PAR), INTENT(IN) :: PGRID_PAR ! grid parameters
56 INTEGER, DIMENSION(:,:),POINTER :: KNEAR ! near mesh indices
57 !
58 !* 0.2 Declaration of other local variables
59 ! ------------------------------------
60 !
61 REAL,DIMENSION(KL) :: ZX
62 REAL,DIMENSION(KL) :: ZY
63 REAL,DIMENSION(KL) :: ZDX
64 REAL,DIMENSION(KL) :: ZDY
65 REAL,DIMENSION(KL) :: ZDIS
66 INTEGER,DIMENSION(KL) :: INDZDIS
67 
68 REAL :: ZMAXVALDIS
69 
70 INTEGER :: JP, ID, ISIZE
71 REAL(KIND=JPRB) :: ZHOOK_HANDLE
72 !
73 !----------------------------------------------------------------------------
74 !
75 IF (lhook) CALL dr_hook('GET_NEAR_MESHES_IGN_1',0,zhook_handle)
76 !
77  CALL get_gridtype_ign(pgrid_par,px=zx,py=zy,pdx=zdx,pdy=zdy)
78 !
79 knear(:,:) = 0
80 !
81 isize = min(knear_nbr,kl)
82 !
83 ! calcul de la distance de tous les points 2 à 2
84 !
85 !
86 IF (lhook) CALL dr_hook('GET_NEAR_MESHES_IGN_1',1,zhook_handle)
87 IF (lhook) CALL dr_hook('GET_NEAR_MESHES_IGN_2',0,zhook_handle)
88 !
89 !$OMP PARALLEL DO PRIVATE(JP,ZDIS,ZMAXVALDIS,INDZDIS,ID)
90 !
91 DO jp=1,kl
92  !
93  IF (nindex(jp)==nrank) THEN
94  !
95  id = nnum(jp)
96  !
97  ! distance du point JP à tous les autres points
98  zdis(:) = sqrt((zx(:)-zx(jp))**2 + (zy(:)-zy(jp))**2)
99  ! distance maximale entre JP et les autres moints
100  zmaxvaldis = 2. * maxval(zdis)
101  zdis(jp) = zmaxvaldis
102 
103  CALL quick_sort(zdis, indzdis)
104  knear(id,1:isize) = indzdis(1:isize)
105  !
106  ENDIF
107  !
108 ENDDO
109 !$OMP END PARALLEL DO
110 !
111 IF (lhook) CALL dr_hook('GET_NEAR_MESHES_IGN_2',1,zhook_handle)
112 !
113 CONTAINS
114 !
115 RECURSIVE SUBROUTINE quick_sort(PLIST, KORDER)
117 ! Quick sort routine from:
118 ! Brainerd, W.S., Goldberg, C.H. & Adams, J.C. (1990) "Programmer's Guide to
119 ! Fortran 90", McGraw-Hill ISBN 0-07-000248-7, pages 149-150.
120 ! Modified by Alan Miller to include an associated integer array which gives
121 ! the positions of the elements in the original order.
122 !
123 IMPLICIT NONE
124 !
125 REAL, DIMENSION (:), INTENT(INOUT) :: PLIST
126 INTEGER, DIMENSION (:), INTENT(OUT) :: KORDER
127 !
128 ! Local variable
129 INTEGER :: JI
130 
131 DO ji = 1, SIZE(plist)
132  korder(ji) = ji
133 END DO
134 
135  CALL quick_sort_1(1, SIZE(plist), plist, korder)
136 
137 END SUBROUTINE quick_sort
138 
139 
140 RECURSIVE SUBROUTINE quick_sort_1(KLEFT_END, KRIGHT_END, PLIST1, KORDER1)
142 INTEGER, INTENT(IN) :: KLEFT_END, KRIGHT_END
143 REAL, DIMENSION (:), INTENT(INOUT) :: PLIST1
144 INTEGER, DIMENSION (:), INTENT(INOUT) :: KORDER1
145 ! Local variables
146 INTEGER :: JI, JJ, ITEMP
147 REAL :: ZREF, ZTEMP
148 INTEGER, PARAMETER :: IMAX_SIMPLE_SORT_SIZE = 6
149 
150 IF (kright_end < kleft_end + imax_simple_sort_size) THEN
151  ! Use interchange sort for small PLISTs
152  CALL interchange_sort(kleft_end, kright_end, plist1, korder1)
153  !
154 ELSE
155  !
156  ! Use partition ("quick") sort
157  ! valeur au centre du tableau
158  zref = plist1((kleft_end + kright_end)/2)
159  ji = kleft_end - 1
160  jj = kright_end + 1
161 
162  DO
163  ! Scan PLIST from left end until element >= ZREF is found
164  DO
165  ji = ji + 1
166  IF (plist1(ji) >= zref) EXIT
167  END DO
168  ! Scan PLIST from right end until element <= ZREF is found
169  DO
170  jj = jj - 1
171  IF (plist1(jj) <= zref) EXIT
172  END DO
173 
174 
175  IF (ji < jj) THEN
176  ! Swap two out-of-order elements
177  ztemp = plist1(ji)
178  plist1(ji) = plist1(jj)
179  plist1(jj) = ztemp
180  itemp = korder1(ji)
181  korder1(ji) = korder1(jj)
182  korder1(jj) = itemp
183  ELSE IF (ji == jj) THEN
184  ji = ji + 1
185  EXIT
186  ELSE
187  EXIT
188  END IF
189  END DO
190 
191  IF (kleft_end < jj) CALL quick_sort_1(kleft_end, jj, plist1, korder1)
192  IF (ji < kright_end) CALL quick_sort_1(ji, kright_end,plist1,korder1)
193 END IF
194 
195 END SUBROUTINE quick_sort_1
196 
197 
198 SUBROUTINE interchange_sort(KLEFT_END, KRIGHT_END, PLIST2, KORDER2)
200 INTEGER, INTENT(IN) :: KLEFT_END, KRIGHT_END
201 REAL, DIMENSION (:), INTENT(INOUT) :: PLIST2
202 INTEGER, DIMENSION (:), INTENT(INOUT) :: KORDER2
203 ! Local variables
204 INTEGER :: JI, JJ, ITEMP
205 REAL :: ZTEMP
206 
207 ! boucle sur tous les points
208 DO ji = kleft_end, kright_end - 1
209  !
210  ! boucle sur les points suivants le point JI
211  DO jj = ji+1, kright_end
212  !
213  ! si la distance de JI au point est plus grande que celle de JJ
214  IF (plist2(ji) > plist2(jj)) THEN
215  ! distance de JI au point (la plus grande)
216  ztemp = plist2(ji)
217  ! le point JJ est déplacé à l'indice JI dans le tableau
218  plist2(ji) = plist2(jj)
219  ! le point JI est déplacé à l'indice JJ dans le tableau
220  plist2(jj) = ztemp
221  ! indice du point JI dans le tableau
222  itemp = korder2(ji)
223  ! l'indice du point JJ est mis à la place JI
224  korder2(ji) = korder2(jj)
225  ! l'indice du point JI est mis à la place JJ
226  korder2(jj) = itemp
227  END IF
228  !
229  END DO
230  !
231 END DO
232 
233 END SUBROUTINE interchange_sort
234 !
235 !-------------------------------------------------------------------------------
236 !
237 END SUBROUTINE get_near_meshes_ign
subroutine get_gridtype_ign(PGRID_PAR, KLAMBERT, KL, PX, PY, PDX, PDY, KDIMX, KDIMY, PXALL, PYALL)
integer, dimension(:), allocatable nnum
subroutine get_near_meshes_ign(KGRID_PAR, KL, PGRID_PAR, KNEAR_NBR, KN
integer, parameter jprb
Definition: parkind1.F90:32
recursive subroutine quick_sort(PLIST, KORDER)
logical lhook
Definition: yomhook.F90:15
integer, dimension(:), allocatable nindex
recursive subroutine quick_sort_1(KLEFT_END, KRIGHT_END, PLIST1, KORDER1
subroutine interchange_sort(KLEFT_END, KRIGHT_END, PLIST2, KORDER2)