FV3 Bundle
Search_Utility.f90
Go to the documentation of this file.
1 !
2 ! Search_Utility
3 !
4 ! Module containing data searching routines
5 !
6 !
7 ! CREATION HISTORY:
8 ! Written by: Paul van Delst, 06-Oct-2006
9 ! paul.vandelst@noaa.gov
10 !
11 
13 
14  ! ------------------
15  ! Environment set up
16  ! ------------------
17  ! Modules used
18  USE type_kinds, ONLY: fp
20  ! Disable all implicit typing
21  IMPLICIT NONE
22 
23 
24  ! ------------
25  ! Visibilities
26  ! ------------
27  PRIVATE
28  PUBLIC :: value_locate
29  PUBLIC :: bisection_search
30 
31 
32  ! -----------------
33  ! Module parameters
34  ! -----------------
35  CHARACTER(*), PARAMETER :: module_version_id = &
36  '$Id: Search_Utility.f90 60152 2015-08-13 19:19:13Z paul.vandelst@noaa.gov $'
37 
38 
39 CONTAINS
40 
41 
42 !------------------------------------------------------------------------------
43 !
44 ! NAME:
45 ! Bisection_Search
46 !
47 ! PURPOSE:
48 ! Function to search an array using the bisection method. This function
49 ! is an adaptation from Numerical Recipes and is most efficient across
50 ! multiple calls when the value to be searched for in the array occurs
51 ! randomly.
52 !
53 ! CALLING SEQUENCE:
54 ! j = Bisection_Search( x, u, & ! Input
55 ! xLower=xLower, & ! Optional input
56 ! xUpper=xUpper ) ! Optional input
57 !
58 ! INPUT ARGUMENTS:
59 ! x: The array to be searched.
60 ! UNITS: N/A
61 ! TYPE: REAL(fp)
62 ! DIMENSION: Rank-1
63 ! ATTRIBUTES: INTENT(IN)
64 !
65 ! u: The value to be searched for in the array.
66 ! UNITS: N/A
67 ! TYPE: REAL(fp)
68 ! DIMENSION: Scalar
69 ! ATTRIBUTES: INTENT(IN)
70 !
71 ! OPTIONAL INPUT ARGUMENTS:
72 ! xLower: Set this optional argument to the index of the input
73 ! array corresponding to the LOWER search boundary.
74 ! If not specified, the default value is 1.
75 ! UNITS: N/A
76 ! TYPE: INTEGER
77 ! DIMENSION: Scalar
78 ! ATTRIBUTES: INTENT(IN), OPTIONAL
79 !
80 ! xUpper: Set this optional argument to the index of the input
81 ! array corresponding to the UPPER search boundary.
82 ! If not specified, the default value is SIZE(x).
83 ! UNITS: N/A
84 ! TYPE: INTEGER
85 ! DIMENSION: Scalar
86 ! ATTRIBUTES: INTENT(IN), OPTIONAL
87 !
88 ! FUNCTION RESULT:
89 ! j: The lower index of the two values in the input array, x,
90 ! that bracket the input value, u, i.e.
91 ! x(j) < u < x(j+1)
92 ! UNITS: N/A
93 ! TYPE: INTEGER
94 ! DIMENSION: Scalar
95 !
96 ! CREATION HISTORY:
97 ! Written by: Paul van Delst, CIMSS/SSEC 22-Nov-2000
98 ! paul.vandelst@ssec.wisc.edu
99 !
100 !------------------------------------------------------------------------------
101 
102  FUNCTION bisection_search( x, u, xLower, xUpper ) RESULT( j )
103  ! Arguments
104  REAL(fp), DIMENSION(:), INTENT(IN) :: x
105  REAL(fp), INTENT(IN) :: u
106  INTEGER, OPTIONAL, INTENT(IN) :: xlower
107  INTEGER, OPTIONAL, INTENT(IN) :: xupper
108  ! Function result
109  INTEGER :: j
110  ! Local variables
111  INTEGER :: n
112  INTEGER :: jlower
113  INTEGER :: jmiddle
114  INTEGER :: jupper
115 
116  ! Set up
117  n = SIZE( x )
118 
119  ! Initialise upper and lower limits to
120  ! the valid maximums, 1 and n
121  IF ( PRESENT(xlower) ) THEN
122  jlower = xlower
123  ELSE
124  jlower = 1
125  END IF
126 
127  IF ( PRESENT(xupper) ) THEN
128  jupper = xupper
129  ELSE
130  jupper = n
131  END IF
132 
133 
134  ! Search for the required index by bisection
135  bisection_search_loop: DO
136 
137  ! If the index ranges have converged, we're done
138  IF ( (jupper-jlower) <= 1 ) EXIT bisection_search_loop
139 
140  ! Define a middle point
141  jmiddle = ( jlower + jupper ) / 2
142 
143  ! Which half is the required value in?
144  IF ( ( x(n) > x(1) ) .EQV. ( u > x(jmiddle) ) ) THEN
145  jlower = jmiddle ! The "upper" half
146  ELSE
147  jupper = jmiddle ! The "lower" half
148  END IF
149 
150  END DO bisection_search_loop
151 
152  ! Define the return value
153  j = jlower
154 
155  END FUNCTION bisection_search
156 
157 
158 !------------------------------------------------------------------------------
159 !
160 ! NAME:
161 ! Value_Locate
162 !
163 ! PURPOSE:
164 ! Function that finds the intervals within a given monotonic
165 ! vector that brackets a given set of one or more search values.
166 !
167 ! This function is an adaptation of the locate() routine in
168 ! Numerical Recipes and uses the bisection method to locate the
169 ! interval.
170 !
171 ! CALLING SEQUENCE:
172 ! j = Value_Locate( x, u ) ! Input
173 !
174 ! INPUT ARGUMENTS:
175 ! x: The array to be searched.
176 ! UNITS: N/A
177 ! TYPE: REAL(fp)
178 ! DIMENSION: Rank-1
179 ! ATTRIBUTES: INTENT(IN)
180 !
181 ! u: The array of values to be searched for in the array.
182 ! UNITS: N/A
183 ! TYPE: REAL(fp)
184 ! DIMENSION: Rank-1
185 ! ATTRIBUTES: INTENT(IN)
186 !
187 ! FUNCTION RESULT:
188 ! j: The integer array of lower indices of the two values in
189 ! the input array, x, that bracket the input values, u.
190 ! E.g. for a given u(i):
191 ! x(j) < u(i) < x(j+1)
192 ! UNITS: N/A
193 ! TYPE: INTEGER
194 ! DIMENSION: Rank-1, same size as u input argument.
195 !
196 ! CREATION HISTORY:
197 ! Written by: Paul van Delst, CIMSS/SSEC 22-Nov-2000
198 ! paul.vandelst@ssec.wisc.edu
199 !
200 !------------------------------------------------------------------------------
201 
202  FUNCTION value_locate( x, u ) RESULT( j )
203  ! Arguments
204  REAL(fp), DIMENSION(:), INTENT(IN) :: x
205  REAL(fp), DIMENSION(:), INTENT(IN) :: u
206  ! Function result
207  INTEGER, DIMENSION(SIZE(u)) :: j
208  ! Local variables
209  INTEGER :: nx
210  INTEGER :: nu, iu
211  INTEGER :: xlower, xupper
212  LOGICAL :: ascending
213 
214  ! Set up
215  nx = SIZE(x)
216  nu = SIZE(u)
217 
218  ! Determine if arrays are sorted in ascending or descending order
219  IF ( x(nx) > x(1) .AND. u(nu) > u(1) ) THEN
220  ascending = .true.
221  ELSEIF ( x(nx) < x(1) .AND. u(nu) < u(1) ) THEN
222  ascending = .false.
223  ELSE
224  j(:) = -1
225  RETURN
226  END IF
227 
228  ! Perform the bisection search for each element of u
229  IF ( ascending ) THEN
230  ! Going up
231  xlower = 1
232  DO iu = 1, nu
233  j(iu) = bisection_search( x, u(iu), xlower = xlower )
234  xlower = max( 1, j(iu) )
235  END DO
236  ELSE
237  ! Going down
238  xupper = nx
239  DO iu = 1, nu
240  j(iu) = bisection_search( x, u(iu), xupper = xupper )
241  xlower = min( j(iu), nx )
242  END DO
243  END IF
244 
245  END FUNCTION value_locate
246 
247 END MODULE search_utility
integer, parameter, public failure
integer, parameter, public fp
Definition: Type_Kinds.f90:124
recursive subroutine, public display_message(Routine_Name, Message, Error_State, Message_Log)
character(*), parameter module_version_id
#define max(a, b)
Definition: mosaic_util.h:33
#define min(a, b)
Definition: mosaic_util.h:32
integer function, dimension(size(u)), public value_locate(x, u)
integer, parameter, public success
integer function, public bisection_search(x, u, xLower, xUpper)