1!
2!(c) Matthew Kennel, Institute for Nonlinear Science (2004)
3!
4! Licensed under the Academic Free License version 1.1 found in file LICENSE_kdTree2.txt
5! with additional provisions found in that same file.
6!
7module kdtree2_precision_mod
8 ! MODULE kdtree2_precision_mod (prefix='none' category='8. Low-level utilities and constants')
9 !
10 !: Purpose: Module used by the kdTree2_mod module.
11 !
12 integer, parameter :: sp = kind(0.0)
13 integer, parameter :: dp = kind(0.0d0)
14
15 private :: sp, dp
16
17 !
18 ! You must comment out exactly one
19 ! of the two lines. If you comment
20 ! out kdkind = sp then you get single precision
21 ! and if you comment out kdkind = dp
22 ! you get double precision.
23 !
24
25 !integer, parameter :: kdkind = sp
26 integer, parameter :: kdkind = dp
27 public :: kdkind
28
29end module kdtree2_precision_mod
30
31module kdtree2_priority_queue_mod
32 ! MODULE kdtree2_priority_queue_mod (prefix='none' category='8. Low-level utilities and constants')
33 !
34 !: Purpose: Module used by the kdTree2_mod module.
35 !
36 use utilities_mod
37 use kdtree2_precision_mod
38 !
39 ! maintain a priority queue (PQ) of data, pairs of 'priority/payload',
40 ! implemented with a binary heap. This is the type, and the 'dis' field
41 ! is the priority.
42 !
43 type kdtree2_result
44 ! a pair of distances, indexes
45 real(kdkind) :: dis!=0.0
46 integer :: idx!=-1 Initializers cause some bugs in compilers.
47 end type kdtree2_result
48 !
49 ! A heap-based priority queue lets one efficiently implement the following
50 ! operations, each in log(N) time, as opposed to linear time.
51 !
52 ! 1) add a datum (push a datum onto the queue, increasing its length)
53 ! 2) return the priority value of the maximum priority element
54 ! 3) pop-off (and delete) the element with the maximum priority, decreasing
55 ! the size of the queue.
56 ! 4) replace the datum with the maximum priority with a supplied datum
57 ! (of either higher or lower priority), maintaining the size of the
58 ! queue.
59 !
60 !
61 ! In the k-d tree case, the 'priority' is the square distance of a point in
62 ! the data set to a reference point. The goal is to keep the smallest M
63 ! distances to a reference point. The tree algorithm searches terminal
64 ! nodes to decide whether to add points under consideration.
65 !
66 ! A priority queue is useful here because it lets one quickly return the
67 ! largest distance currently existing in the list. If a new candidate
68 ! distance is smaller than this, then the new candidate ought to replace
69 ! the old candidate. In priority queue terms, this means removing the
70 ! highest priority element, and inserting the new one.
71 !
72 ! Algorithms based on Cormen, Leiserson, Rivest, _Introduction
73 ! to Algorithms_, 1990, with further optimization by the author.
74 !
75 ! Originally informed by a C implementation by Sriranga Veeraraghavan.
76 !
77 ! This module is not written in the most clear way, but is implemented such
78 ! for speed, as it its operations will be called many times during searches
79 ! of large numbers of neighbors.
80 !
81 type pq
82 !
83 ! The priority queue consists of elements
84 ! priority(1:heap_size), with associated payload(:).
85 !
86 ! There are heap_size active elements.
87 ! Assumes the allocation is always sufficient. Will NOT increase it
88 ! to match.
89 integer :: heap_size = 0
90 type(kdtree2_result), pointer :: elems(:)
91 end type pq
92
93 public :: kdtree2_result
94
95 public :: pq
96 public :: pq_create
97 public :: pq_delete, pq_insert
98 public :: pq_extract_max, pq_max, pq_replace_max, pq_maxpri
99 private
100
101contains
102
103
104 function pq_create(results_in) result(res)
105 !:Purpose: Create a priority queue from ALREADY allocated
106 ! array pointers for storage. NOTE! It will NOT
107 ! add any alements to the heap, i.e. any existing
108 ! data in the input arrays will NOT be used and may
109 ! be overwritten.
110 !
111
112 ! usage:
113 ! real(kdkind), pointer :: x(:)
114 ! integer, pointer :: k(:)
115 ! allocate(x(1000),k(1000))
116 ! pq => pq_create(x,k)
117 !
118 type(kdtree2_result), target:: results_in(:)
119 type(pq) :: res
120 !
121 !
122 integer :: nalloc
123
124 nalloc = size(results_in,1)
125 if (nalloc .lt. 1) then
126 write (*,*) 'PQ_CREATE: error, input arrays must be allocated.'
127 end if
128 res%elems => results_in
129 res%heap_size = 0
130 return
131 end function pq_create
132
133
134 subroutine heapify(a,i_in)
135 !:Purpose: take a heap rooted at 'i' and force it to be in the
136 ! heap canonical form. This is performance critical
137 ! and has been tweaked a little to reflect this.
138 !
139 type(pq),pointer :: a
140 integer, intent(in) :: i_in
141 !
142 integer :: i, l, r, largest
143
144 real(kdkind) :: pri_i, pri_l, pri_r, pri_largest
145
146
147 type(kdtree2_result) :: temp
148
149 i = i_in
150
151bigloop: do
152 l = 2*i ! left(i)
153 r = l+1 ! right(i)
154 !
155 ! set 'largest' to the index of either i, l, r
156 ! depending on whose priority is largest.
157 !
158 ! note that l or r can be larger than the heap size
159 ! in which case they do not count.
160
161
162 ! does left child have higher priority?
163 if (l .gt. a%heap_size) then
164 ! we know that i is the largest as both l and r are invalid.
165 exit
166 else
167 pri_i = a%elems(i)%dis
168 pri_l = a%elems(l)%dis
169 if (pri_l .gt. pri_i) then
170 largest = l
171 pri_largest = pri_l
172 else
173 largest = i
174 pri_largest = pri_i
175 endif
176
177 !
178 ! between i and l we have a winner
179 ! now choose between that and r.
180 !
181 if (r .le. a%heap_size) then
182 pri_r = a%elems(r)%dis
183 if (pri_r .gt. pri_largest) then
184 largest = r
185 endif
186 endif
187 endif
188
189 if (largest .ne. i) then
190 ! swap data in nodes largest and i, then heapify
191
192 temp = a%elems(i)
193 a%elems(i) = a%elems(largest)
194 a%elems(largest) = temp
195 !
196 ! Canonical heapify() algorithm has tail-ecursive call:
197 !
198 ! call heapify(a,largest)
199 ! we will simulate with cycle
200 !
201 i = largest
202 cycle bigloop ! continue the loop
203 else
204 return ! break from the loop
205 end if
206 enddo bigloop
207 return
208 end subroutine heapify
209
210 subroutine pq_max(a,e)
211 !:Purpose: return the priority and its payload of the maximum priority element
212 ! on the queue, which should be the first one, if it is
213 ! in heapified form.
214 !
215 type(pq),pointer :: a
216 type(kdtree2_result),intent(out) :: e
217
218 if (a%heap_size .gt. 0) then
219 e = a%elems(1)
220 else
221 call utl_abort('kdtree2_mod-PQ_MAX: ERROR, heap_size < 1')
222 endif
223 return
224 end subroutine pq_max
225
226 real(kdkind) function pq_maxpri(a)
227 type(pq), pointer :: a
228
229 if (a%heap_size .gt. 0) then
230 pq_maxpri = a%elems(1)%dis
231 else
232 call utl_abort('kdtrees_mod-PQ_MAX_PRI: ERROR, heapsize < 1')
233 endif
234 return
235 end function pq_maxpri
236
237 subroutine pq_extract_max(a,e)
238 !:Purpose: return the priority and payload of maximum priority
239 ! element, and remove it from the queue.
240 ! (equivalent to 'pop()' on a stack)
241 !
242 type(pq),pointer :: a
243 type(kdtree2_result), intent(out) :: e
244
245 if (a%heap_size .ge. 1) then
246 !
247 ! return max as first element
248 !
249 e = a%elems(1)
250
251 !
252 ! move last element to first
253 !
254 a%elems(1) = a%elems(a%heap_size)
255 a%heap_size = a%heap_size-1
256 call heapify(a,1)
257 return
258 else
259 call utl_abort('kdtree2_mod-PQ_EXTRACT_MAX: error, attempted to pop non-positive PQ')
260 end if
261
262 end subroutine pq_extract_max
263
264
265 real(kdkind) function pq_insert(a,dis,idx)
266 !:Purpose: Insert a new element and return the new maximum priority,
267 ! which may or may not be the same as the old maximum priority.
268 !
269 type(pq),pointer :: a
270 real(kdkind), intent(in) :: dis
271 integer, intent(in) :: idx
272 ! type(kdtree2_result), intent(in) :: e
273 !
274 integer :: i, isparent
275 real(kdkind) :: parentdis
276 !
277
278 ! if (a%heap_size .ge. a%max_elems) then
279 ! write (*,*) 'PQ_INSERT: error, attempt made to insert element on full PQ'
280 ! stop
281 ! else
282 a%heap_size = a%heap_size + 1
283 i = a%heap_size
284
285 do while (i .gt. 1)
286 isparent = int(i/2)
287 parentdis = a%elems(isparent)%dis
288 if (dis .gt. parentdis) then
289 ! move what was in i's parent into i.
290 a%elems(i)%dis = parentdis
291 a%elems(i)%idx = a%elems(isparent)%idx
292 i = isparent
293 else
294 exit
295 endif
296 end do
297
298 ! insert the element at the determined position
299 a%elems(i)%dis = dis
300 a%elems(i)%idx = idx
301
302 pq_insert = a%elems(1)%dis
303 return
304 ! end if
305
306 end function pq_insert
307
308 subroutine pq_adjust_heap(a,i)
309 type(pq),pointer :: a
310 integer, intent(in) :: i
311 !
312 ! nominally arguments (a,i), but specialize for a=1
313 !
314 ! This routine assumes that the trees with roots 2 and 3 are already heaps, i.e.
315 ! the children of '1' are heaps. When the procedure is completed, the
316 ! tree rooted at 1 is a heap.
317 real(kdkind) :: prichild
318 integer :: parent, child, N
319
320 type(kdtree2_result) :: e
321
322 e = a%elems(i)
323
324 parent = i
325 child = 2*i
326 N = a%heap_size
327
328 do while (child .le. N)
329 if (child .lt. N) then
330 if (a%elems(child)%dis .lt. a%elems(child+1)%dis) then
331 child = child+1
332 endif
333 endif
334 prichild = a%elems(child)%dis
335 if (e%dis .ge. prichild) then
336 exit
337 else
338 ! move child into parent.
339 a%elems(parent) = a%elems(child)
340 parent = child
341 child = 2*parent
342 end if
343 end do
344 a%elems(parent) = e
345 return
346 end subroutine pq_adjust_heap
347
348
349 real(kdkind) function pq_replace_max(a,dis,idx)
350 !:Purpose: Replace the extant maximum priority element
351 ! in the PQ with (dis,idx). Return
352 ! the new maximum priority, which may be larger
353 ! or smaller than the old one.
354 !
355 type(pq),pointer :: a
356 real(kdkind), intent(in) :: dis
357 integer, intent(in) :: idx
358! type(kdtree2_result), intent(in) :: e
359 ! not tested as well!
360
361 integer :: parent, child, N
362 real(kdkind) :: prichild, prichildp1
363
364 type(kdtree2_result) :: etmp
365
366 if (.true.) then
367 N=a%heap_size
368 if (N .ge. 1) then
369 parent =1
370 child=2
371
372 loop: do while (child .le. N)
373 prichild = a%elems(child)%dis
374
375 !
376 ! posibly child+1 has higher priority, and if
377 ! so, get it, and increment child.
378 !
379
380 if (child .lt. N) then
381 prichildp1 = a%elems(child+1)%dis
382 if (prichild .lt. prichildp1) then
383 child = child+1
384 prichild = prichildp1
385 endif
386 endif
387
388 if (dis .ge. prichild) then
389 exit loop
390 ! we have a proper place for our new element,
391 ! bigger than either children's priority.
392 else
393 ! move child into parent.
394 a%elems(parent) = a%elems(child)
395 parent = child
396 child = 2*parent
397 end if
398 end do loop
399 a%elems(parent)%dis = dis
400 a%elems(parent)%idx = idx
401 pq_replace_max = a%elems(1)%dis
402 else
403 a%elems(1)%dis = dis
404 a%elems(1)%idx = idx
405 pq_replace_max = dis
406 endif
407 else
408 !
409 ! slower version using elementary pop and push operations.
410 !
411 call pq_extract_max(a,etmp)
412 etmp%dis = dis
413 etmp%idx = idx
414 pq_replace_max = pq_insert(a,dis,idx)
415 endif
416 return
417 end function pq_replace_max
418
419 subroutine pq_delete(a,i)
420 !:Purpose: delete item with index 'i'
421 !
422 type(pq),pointer :: a
423 integer :: i
424
425 if ((i .lt. 1) .or. (i .gt. a%heap_size)) then
426 call utl_abort('kdtree2_mod-PQ_DELETE: error, attempt to remove out of bounds element.')
427 endif
428
429 ! swap the item to be deleted with the last element
430 ! and shorten heap by one.
431 a%elems(i) = a%elems(a%heap_size)
432 a%heap_size = a%heap_size - 1
433
434 call heapify(a,i)
435
436 end subroutine pq_delete
437
438end module kdtree2_priority_queue_mod
439
440
441module kdTree2_mod
442 ! MODULE kdTree2_mod (prefix='kdtree2' category='8. Low-level utilities and constants')
443 !
444 !:Purpose: An implementation of the kdtree algorithm for efficiently finding nearby
445 ! locations (first used in LETKF to find all obs near an analysis grid point).
446 ! Written by Matt Kennel.
447 !
448 use utilities_mod
449 use kdtree2_precision_mod
450 use kdtree2_priority_queue_mod
451 use earthConstants_mod
452 ! K-D tree routines in Fortran 90 by Matt Kennel.
453 ! Original program was written in Sather by Steve Omohundro and
454 ! Matt Kennel. Only the Euclidean metric is supported.
455 !
456 !
457 ! This module is identical to 'kd_tree', except that the order
458 ! of subscripts is reversed in the data file.
459 ! In otherwords for an embedding of N D-dimensional vectors, the
460 ! data file is here, in natural Fortran order data(1:D, 1:N)
461 ! because Fortran lays out columns first,
462 !
463 ! whereas conventionally (C-style) it is data(1:N,1:D)
464 ! as in the original kd_tree module.
465 !
466 !-------------DATA TYPE, CREATION, DELETION---------------------
467 public :: kdkind
468 public :: kdtree2, kdtree2_result, tree_node, kdtree2_create, kdtree2_destroy
469 !---------------------------------------------------------------
470 !-------------------SEARCH ROUTINES-----------------------------
471 public :: kdtree2_n_nearest,kdtree2_n_nearest_around_point
472 ! Return fixed number of nearest neighbors around arbitrary vector,
473 ! or extant point in dataset, with decorrelation window.
474 !
475 public :: kdtree2_r_nearest, kdtree2_r_nearest_around_point
476 ! Return points within a fixed ball of arb vector/extant point
477 !
478 public :: kdtree2_sort_results
479 ! Sort, in order of increasing distance, rseults from above.
480 !
481 public :: kdtree2_r_count, kdtree2_r_count_around_point
482 ! Count points within a fixed ball of arb vector/extant point
483 !
484 public :: kdtree2_n_nearest_brute_force, kdtree2_r_nearest_brute_force
485 ! brute force of kdtree2_[n|r]_nearest
486 !----------------------------------------------------------------
487
488 public :: kdtree2_3dPosition
489
490 integer, parameter :: bucket_size = 12
491 ! The maximum number of points to keep in a terminal node.
492
493 type interval
494 real(kdkind) :: lower,upper
495 end type interval
496
497 type :: tree_node
498 ! an internal tree node
499 private
500 integer :: cut_dim
501 ! the dimension to cut
502 real(kdkind) :: cut_val
503 ! where to cut the dimension
504 real(kdkind) :: cut_val_left, cut_val_right
505 ! improved cutoffs knowing the spread in child boxes.
506 integer :: l, u
507 type (tree_node), pointer :: left, right
508 type(interval), pointer :: box(:) => null()
509 ! child pointers
510 ! Points included in this node are indexes[k] with k \in [l,u]
511
512
513 end type tree_node
514
515 type :: kdtree2
516 ! Global information about the tree, one per tree
517 integer :: dimen=0, n=0
518 ! dimensionality and total # of points
519 real(kdkind), pointer :: the_data(:,:) => null()
520 ! pointer to the actual data array
521 !
522 ! IMPORTANT NOTE: IT IS DIMENSIONED the_data(1:d,1:N)
523 ! which may be opposite of what may be conventional.
524 ! This is, because in Fortran, the memory layout is such that
525 ! the first dimension is in sequential order. Hence, with
526 ! (1:d,1:N), all components of the vector will be in consecutive
527 ! memory locations. The search time is dominated by the
528 ! evaluation of distances in the terminal nodes. Putting all
529 ! vector components in consecutive memory location improves
530 ! memory cache locality, and hence search speed, and may enable
531 ! vectorization on some processors and compilers.
532
533 integer, pointer :: ind(:) => null()
534 ! permuted index into the data, so that indexes[l..u] of some
535 ! bucket represent the indexes of the actual points in that
536 ! bucket.
537 logical :: sort = .false.
538 ! do we always sort output results?
539 logical :: rearrange = .false.
540 real(kdkind), pointer :: rearranged_data(:,:) => null()
541 ! if (rearrange .eqv. .true.) then rearranged_data has been
542 ! created so that rearranged_data(:,i) = the_data(:,ind(i)),
543 ! permitting search to use more cache-friendly rearranged_data, at
544 ! some initial computation and storage cost.
545 type (tree_node), pointer :: root => null()
546 ! root pointer of the tree
547 end type kdtree2
548
549
550 type :: tree_search_record
551 !
552 ! One of these is created for each search.
553 !
554 private
555 !
556 ! Many fields are copied from the tree structure, in order to
557 ! speed up the search.
558 !
559 integer :: dimen
560 integer :: nn, nfound
561 real(kdkind) :: ballsize
562 integer :: centeridx=999, correltime=9999
563 ! exclude points within 'correltime' of 'centeridx', iff centeridx >= 0
564 integer :: nalloc ! how much allocated for results(:)?
565 logical :: rearrange ! are the data rearranged or original?
566 ! did the # of points found overflow the storage provided?
567 logical :: overflow
568 real(kdkind), pointer :: qv(:) ! query vector
569 type(kdtree2_result), pointer :: results(:) ! results
570 type(pq) :: pq
571 real(kdkind), pointer :: data(:,:) ! temp pointer to data
572 integer, pointer :: ind(:) ! temp pointer to indexes
573 end type tree_search_record
574
575 private
576 ! everything else is private.
577
578 type(tree_search_record), save, allocatable, target :: sr(:) ! A GLOBAL VARIABLE for search
579
580contains
581
582 function kdtree2_create(input_data,dim,sort,rearrange) result (mr)
583 !:Purpose: Create the actual tree structure, given an input array of data.
584
585 ! Note, input data is input_data(1:d,1:N), NOT the other way around.
586 ! THIS IS THE REVERSE OF THE PREVIOUS VERSION OF THIS MODULE.
587 ! The reason for it is cache friendliness, improving performance.
588 !
589 ! Optional arguments: If 'dim' is specified, then the tree
590 ! will only search the first 'dim' components
591 ! of input_data, otherwise, dim is inferred
592 ! from SIZE(input_data,1).
593 !
594 ! if sort .eqv. .true. then output results
595 ! will be sorted by increasing distance.
596 ! default=.false., as it is faster to not sort.
597 !
598 ! if rearrange .eqv. .true. then an internal
599 ! copy of the data, rearranged by terminal node,
600 ! will be made for cache friendliness.
601 ! default=.true., as it speeds searches, but
602 ! building takes longer, and extra memory is used.
603 !
604 ! .. Function Return Cut_value ..
605 type (kdtree2), pointer :: mr
606 integer, intent(in), optional :: dim
607 logical, intent(in), optional :: sort
608 logical, intent(in), optional :: rearrange
609 ! ..
610 ! .. Array Arguments ..
611 real(kdkind), target :: input_data(:,:)
612 !
613 integer :: i, numthread, mythread
614 integer, external :: omp_get_thread_num, omp_get_num_threads
615 ! ..
616 allocate (mr)
617 mr%the_data => input_data
618 ! pointer assignment
619
620 if (present(dim)) then
621 mr%dimen = dim
622 else
623 mr%dimen = size(input_data,1)
624 end if
625 mr%n = size(input_data,2)
626
627 if (mr%n < 1) then
628 ! unlikely to be correct
629 write (*,*) 'KD_TREE_TRANS: likely user error.'
630 write (*,*) 'KD_TREE_TRANS: You passed in matrix with D=',mr%dimen
631 write (*,*) 'KD_TREE_TRANS: and N=',mr%n
632 write (*,*) 'KD_TREE_TRANS: note, that new format is data(1:D,1:N)'
633 write (*,*) 'KD_TREE_TRANS: with usually N >> D. If N =approx= D, then a k-d tree'
634 write (*,*) 'KD_TREE_TRANS: is not an appropriate data structure.'
635 call utl_abort('kdtree2_create: supplied array has no data')
636 end if
637
638 !$OMP PARALLEL PRIVATE(mythread)
639 mythread = omp_get_thread_num()
640 if ( mythread == 0 ) then
641 numthread = omp_get_num_threads()
642 end if
643 !$OMP END PARALLEL
644
645 if ( .not. allocated(sr) ) allocate(sr(0:numthread-1))
646
647 call build_tree(mr)
648
649 if (present(sort)) then
650 mr%sort = sort
651 else
652 mr%sort = .false.
653 endif
654
655 if (present(rearrange)) then
656 mr%rearrange = rearrange
657 else
658 mr%rearrange = .true.
659 endif
660
661 if (mr%rearrange) then
662 allocate(mr%rearranged_data(mr%dimen,mr%n))
663 do i=1,mr%n
664 mr%rearranged_data(:,i) = mr%the_data(:, &
665 mr%ind(i))
666 enddo
667 else
668 nullify(mr%rearranged_data)
669 endif
670
671 end function kdtree2_create
672
673 subroutine build_tree(tp)
674 type (kdtree2), pointer :: tp
675 ! ..
676 integer :: j
677 type(tree_node), pointer :: dummy => null()
678 ! ..
679 allocate (tp%ind(tp%n))
680 forall (j=1:tp%n)
681 tp%ind(j) = j
682 end forall
683 tp%root => build_tree_for_range(tp,1,tp%n, dummy)
684 end subroutine build_tree
685
686 recursive function build_tree_for_range(tp,l,u,parent) result (res)
687 ! .. Function Return Cut_value ..
688 type (tree_node), pointer :: res
689 ! ..
690 ! .. Structure Arguments ..
691 type (kdtree2), pointer :: tp
692 type (tree_node),pointer :: parent
693 ! ..
694 ! .. Scalar Arguments ..
695 integer, intent (In) :: l, u
696 ! ..
697 ! .. Local Scalars ..
698 integer :: i, c, m, dimen
699 logical :: recompute
700 real(kdkind) :: average
701
702 ! first compute min and max
703 dimen = tp%dimen
704 allocate (res)
705 allocate(res%box(dimen))
706
707 ! First, compute an APPROXIMATE bounding box of all points associated with this node.
708 if ( u < l ) then
709 ! no points in this box
710 nullify(res)
711 return
712 end if
713
714 if ((u-l)<=bucket_size) then
715 !
716 ! always compute true bounding box for terminal nodes.
717 !
718 do i=1,dimen
719 call spread_in_coordinate(tp,i,l,u,res%box(i))
720 end do
721 res%cut_dim = 0
722 res%cut_val = 0.0
723 res%l = l
724 res%u = u
725 res%left =>null()
726 res%right => null()
727 else
728 !
729 ! modify approximate bounding box. This will be an
730 ! overestimate of the true bounding box, as we are only recomputing
731 ! the bounding box for the dimension that the parent split on.
732 !
733 ! Going to a true bounding box computation would significantly
734 ! increase the time necessary to build the tree, and usually
735 ! has only a very small difference. This box is not used
736 ! for searching but only for deciding which coordinate to split on.
737 !
738 do i=1,dimen
739 recompute=.true.
740 if (associated(parent)) then
741 if (i .ne. parent%cut_dim) then
742 recompute=.false.
743 end if
744 endif
745 if (recompute) then
746 call spread_in_coordinate(tp,i,l,u,res%box(i))
747 else
748 res%box(i) = parent%box(i)
749 endif
750 end do
751
752
753 c = maxloc(res%box(1:dimen)%upper-res%box(1:dimen)%lower,1)
754 !
755 ! c is the identity of which coordinate has the greatest spread.
756 !
757
758 if (.false.) then
759 ! select exact median to have fully balanced tree.
760 m = (l+u)/2
761 call select_on_coordinate(tp%the_data,tp%ind,c,m,l,u)
762 else
763 !
764 ! select point halfway between min and max, as per A. Moore,
765 ! who says this helps in some degenerate cases, or
766 ! actual arithmetic average.
767 !
768 if (.true.) then
769 ! actually compute average
770 average = sum(tp%the_data(c,tp%ind(l:u))) / real(u-l+1,kdkind)
771 else
772 average = (res%box(c)%upper + res%box(c)%lower)/2.0
773 endif
774
775 res%cut_val = average
776 m = select_on_coordinate_value(tp%the_data,tp%ind,c,average,l,u)
777 endif
778
779 ! moves indexes around
780 res%cut_dim = c
781 res%l = l
782 res%u = u
783! res%cut_val = tp%the_data(c,tp%ind(m))
784
785 res%left => build_tree_for_range(tp,l,m,res)
786 res%right => build_tree_for_range(tp,m+1,u,res)
787
788 if (associated(res%right) .eqv. .false.) then
789 res%box = res%left%box
790 res%cut_val_left = res%left%box(c)%upper
791 res%cut_val = res%cut_val_left
792 elseif (associated(res%left) .eqv. .false.) then
793 res%box = res%right%box
794 res%cut_val_right = res%right%box(c)%lower
795 res%cut_val = res%cut_val_right
796 else
797 res%cut_val_right = res%right%box(c)%lower
798 res%cut_val_left = res%left%box(c)%upper
799 res%cut_val = (res%cut_val_left + res%cut_val_right)/2
800
801
802 ! now remake the true bounding box for self.
803 ! Since we are taking unions (in effect) of a tree structure,
804 ! this is much faster than doing an exhaustive
805 ! search over all points
806 res%box%upper = max(res%left%box%upper,res%right%box%upper)
807 res%box%lower = min(res%left%box%lower,res%right%box%lower)
808 endif
809 end if
810 end function build_tree_for_range
811
812 integer function select_on_coordinate_value(v,ind,c,alpha,li,ui) &
813 result(res)
814 !:Purpose: Move elts of ind around between l and u, so that all points
815 ! <= than alpha (in c cooordinate) are first, and then
816 ! all points > alpha are second.
817
818 !
819 ! Algorithm (matt kennel).
820 !
821 ! Consider the list as having three parts: on the left,
822 ! the points known to be <= alpha. On the right, the points
823 ! known to be > alpha, and in the middle, the currently unknown
824 ! points. The algorithm is to scan the unknown points, starting
825 ! from the left, and swapping them so that they are added to
826 ! the left stack or the right stack, as appropriate.
827 !
828 ! The algorithm finishes when the unknown stack is empty.
829 !
830 ! .. Scalar Arguments ..
831 integer, intent (In) :: c, li, ui
832 real(kdkind), intent(in) :: alpha
833 ! ..
834 real(kdkind) :: v(1:,1:)
835 integer :: ind(1:)
836 integer :: tmp
837 ! ..
838 integer :: lb, rb
839 !
840 ! The points known to be <= alpha are in
841 ! [l,lb-1]
842 !
843 ! The points known to be > alpha are in
844 ! [rb+1,u].
845 !
846 ! Therefore we add new points into lb or
847 ! rb as appropriate. When lb=rb
848 ! we are done. We return the location of the last point <= alpha.
849 !
850 !
851 lb = li; rb = ui
852
853 do while (lb < rb)
854 if ( v(c,ind(lb)) <= alpha ) then
855 ! it is good where it is.
856 lb = lb+1
857 else
858 ! swap it with rb.
859 tmp = ind(lb); ind(lb) = ind(rb); ind(rb) = tmp
860 rb = rb-1
861 endif
862 end do
863
864 ! now lb .eq. ub
865 if (v(c,ind(lb)) <= alpha) then
866 res = lb
867 else
868 res = lb-1
869 endif
870
871 ! add a check to prevent something going wrong (Buehner)
872 if (res < li .or. res >= ui) then
873 !write(*,*) 'patch to handle many equal positions:',li,ui,res,v(c,ind(li:ui))
874 res = (li + ui)/2
875 end if
876
877 end function select_on_coordinate_value
878
879 subroutine select_on_coordinate(v,ind,c,k,li,ui)
880 !:Purpose: Move elts of ind around between l and u, so that the kth
881 ! element is >= those below, <= those above, in the coordinate c.
882
883 ! .. Scalar Arguments ..
884 integer, intent (In) :: c, k, li, ui
885 ! ..
886 integer :: i, l, m, s, t, u
887 ! ..
888 real(kdkind) :: v(:,:)
889 integer :: ind(:)
890 ! ..
891 l = li
892 u = ui
893 do while (l<u)
894 t = ind(l)
895 m = l
896 do i = l + 1, u
897 if (v(c,ind(i))<v(c,t)) then
898 m = m + 1
899 s = ind(m)
900 ind(m) = ind(i)
901 ind(i) = s
902 end if
903 end do
904 s = ind(l)
905 ind(l) = ind(m)
906 ind(m) = s
907 if (m<=k) l = m + 1
908 if (m>=k) u = m - 1
909 end do
910 end subroutine select_on_coordinate
911
912 subroutine spread_in_coordinate(tp,c,l,u,interv)
913 !:Purpose: the spread in coordinate 'c', between l and u.
914 ! Return lower bound in 'smin', and upper in 'smax',
915
916 ! ..
917 ! .. Structure Arguments ..
918 type (kdtree2), pointer :: tp
919 type(interval), intent(out) :: interv
920 ! ..
921 ! .. Scalar Arguments ..
922 integer, intent (In) :: c, l, u
923 ! ..
924 ! .. Local Scalars ..
925 real(kdkind) :: last, lmax, lmin, t, smin,smax
926 integer :: i, ulocal
927 ! ..
928 ! .. Local Arrays ..
929 real(kdkind), pointer :: v(:,:)
930 integer, pointer :: ind(:)
931 ! ..
932 v => tp%the_data(1:,1:)
933 ind => tp%ind(1:)
934 smin = v(c,ind(l))
935 smax = smin
936
937 ulocal = u
938
939 do i = l + 2, ulocal, 2
940 lmin = v(c,ind(i-1))
941 lmax = v(c,ind(i))
942 if (lmin>lmax) then
943 t = lmin
944 lmin = lmax
945 lmax = t
946 end if
947 if (smin>lmin) smin = lmin
948 if (smax<lmax) smax = lmax
949 end do
950 if (i==ulocal+1) then
951 last = v(c,ind(ulocal))
952 if (smin>last) smin = last
953 if (smax<last) smax = last
954 end if
955
956 interv%lower = smin
957 interv%upper = smax
958
959 end subroutine spread_in_coordinate
960
961
962 subroutine kdtree2_destroy(tp)
963 !:Purpose: Deallocates all memory for the tree, except input data matrix
964
965 ! .. Structure Arguments ..
966 type (kdtree2), pointer :: tp
967 ! ..
968 call destroy_node(tp%root)
969
970 deallocate (tp%ind)
971 nullify (tp%ind)
972
973 if (tp%rearrange) then
974 deallocate(tp%rearranged_data)
975 nullify(tp%rearranged_data)
976 endif
977
978 nullify(tp%the_data)
979
980 deallocate(tp)
981 nullify(tp)
982 return
983
984 contains
985 recursive subroutine destroy_node(np)
986 ! .. Structure Arguments ..
987 type (tree_node), pointer :: np
988 ! ..
989 ! .. Intrinsic Functions ..
990 intrinsic ASSOCIATED
991 ! ..
992 if (associated(np%left)) then
993 call destroy_node(np%left)
994 nullify (np%left)
995 end if
996 if (associated(np%right)) then
997 call destroy_node(np%right)
998 nullify (np%right)
999 end if
1000 if (associated(np%box)) deallocate(np%box)
1001 deallocate(np)
1002 return
1003
1004 end subroutine destroy_node
1005
1006 end subroutine kdtree2_destroy
1007
1008 subroutine kdtree2_n_nearest(tp,qv,nn,results)
1009 !:Purpose: Find the 'nn' vectors in the tree nearest to 'qv' in euclidean norm
1010 ! returning their indexes and distances in 'indexes' and 'distances'
1011 ! arrays already allocated passed to this subroutine.
1012 type (kdtree2), pointer :: tp
1013 real(kdkind), target, intent (In) :: qv(:)
1014 integer, intent (In) :: nn
1015 type(kdtree2_result), target :: results(:)
1016 integer :: mythread
1017 integer, external :: omp_get_thread_num
1018
1019 mythread = omp_get_thread_num()
1020
1021 sr(mythread)%ballsize = huge(1.0)
1022 sr(mythread)%qv => qv
1023 sr(mythread)%nn = nn
1024 sr(mythread)%nfound = 0
1025 sr(mythread)%centeridx = -1
1026 sr(mythread)%correltime = 0
1027 sr(mythread)%overflow = .false.
1028
1029 sr(mythread)%results => results
1030
1031 sr(mythread)%nalloc = nn ! will be checked
1032
1033 sr(mythread)%ind => tp%ind
1034 sr(mythread)%rearrange = tp%rearrange
1035 if (tp%rearrange) then
1036 sr(mythread)%Data => tp%rearranged_data
1037 else
1038 sr(mythread)%Data => tp%the_data
1039 endif
1040 sr(mythread)%dimen = tp%dimen
1041
1042 call validate_query_storage(nn)
1043 sr(mythread)%pq = pq_create(results)
1044
1045 call search(tp%root)
1046
1047 if (tp%sort) then
1048 call kdtree2_sort_results(nn, results)
1049 endif
1050! deallocate(sr(mythread)%pqp)
1051 return
1052 end subroutine kdtree2_n_nearest
1053
1054 subroutine kdtree2_n_nearest_around_point(tp,idxin,correltime,nn,results)
1055 !:Purpose: Find the 'nn' vectors in the tree nearest to point 'idxin',
1056 ! with correlation window 'correltime', returing results in
1057 ! results(:), which must be pre-allocated upon entry.
1058 type (kdtree2), pointer :: tp
1059 integer, intent (In) :: idxin, correltime, nn
1060 type(kdtree2_result), target :: results(:)
1061 integer :: mythread
1062 integer, external :: omp_get_thread_num
1063
1064 mythread = omp_get_thread_num()
1065
1066 allocate (sr(mythread)%qv(tp%dimen))
1067 sr(mythread)%qv = tp%the_data(:,idxin) ! copy the vector
1068 sr(mythread)%ballsize = huge(1.0) ! the largest real(kdkind) number
1069 sr(mythread)%centeridx = idxin
1070 sr(mythread)%correltime = correltime
1071
1072 sr(mythread)%nn = nn
1073 sr(mythread)%nfound = 0
1074
1075 sr(mythread)%dimen = tp%dimen
1076 sr(mythread)%nalloc = nn
1077
1078 sr(mythread)%results => results
1079
1080 sr(mythread)%ind => tp%ind
1081 sr(mythread)%rearrange = tp%rearrange
1082
1083 if (sr(mythread)%rearrange) then
1084 sr(mythread)%Data => tp%rearranged_data
1085 else
1086 sr(mythread)%Data => tp%the_data
1087 endif
1088
1089 call validate_query_storage(nn)
1090 sr(mythread)%pq = pq_create(results)
1091
1092 call search(tp%root)
1093
1094 if (tp%sort) then
1095 call kdtree2_sort_results(nn, results)
1096 endif
1097 deallocate (sr(mythread)%qv)
1098 return
1099 end subroutine kdtree2_n_nearest_around_point
1100
1101 subroutine kdtree2_r_nearest(tp,qv,r2,nfound,nalloc,results)
1102 !:Purpose: find the nearest neighbors to point 'idxin', within SQUARED
1103 ! Euclidean distance 'r2'. Upon ENTRY, nalloc must be the
1104 ! size of memory allocated for results(1:nalloc). Upon
1105 ! EXIT, nfound is the number actually found within the ball.
1106 !
1107 ! Note that if nfound .gt. nalloc then more neighbors were found
1108 ! than there were storage to store. The resulting list is NOT
1109 ! the smallest ball inside norm r^2
1110 !
1111 ! Results are NOT sorted unless tree was created with sort option.
1112 type (kdtree2), pointer :: tp
1113 real(kdkind), target, intent (In) :: qv(:)
1114 real(kdkind), intent(in) :: r2
1115 integer, intent(out) :: nfound
1116 integer, intent (In) :: nalloc
1117 type(kdtree2_result), target :: results(:)
1118 integer :: mythread
1119 integer, external :: omp_get_thread_num
1120
1121 mythread = omp_get_thread_num()
1122 !
1123 sr(mythread)%qv => qv
1124 sr(mythread)%ballsize = r2
1125 sr(mythread)%nn = 0 ! flag for fixed ball search
1126 sr(mythread)%nfound = 0
1127 sr(mythread)%centeridx = -1
1128 sr(mythread)%correltime = 0
1129
1130 sr(mythread)%results => results
1131
1132 call validate_query_storage(nalloc)
1133 sr(mythread)%nalloc = nalloc
1134 sr(mythread)%overflow = .false.
1135 sr(mythread)%ind => tp%ind
1136 sr(mythread)%rearrange= tp%rearrange
1137
1138 if (tp%rearrange) then
1139 sr(mythread)%Data => tp%rearranged_data
1140 else
1141 sr(mythread)%Data => tp%the_data
1142 endif
1143 sr(mythread)%dimen = tp%dimen
1144
1145 !
1146 !sr(mythread)%dsl = Huge(sr(mythread)%dsl) ! set to huge positive values
1147 !sr(mythread)%il = -1 ! set to invalid indexes
1148 !
1149
1150 call search(tp%root)
1151 nfound = sr(mythread)%nfound
1152
1153 if (sr(mythread)%overflow) then
1154 write (*,*) 'KD_TREE_TRANS: warning! return from kdtree2_r_nearest found more neighbors'
1155 write (*,*) 'KD_TREE_TRANS: than storage was provided for. Answer is NOT smallest ball'
1156 write (*,*) 'KD_TREE_TRANS: with that number of neighbors! I.e. it is wrong.'
1157 write (*,*) 'KD_TREE_TRANS: nfound =', nfound, ', nalloc =', nalloc
1158 endif
1159
1160 if (tp%sort .and. .not.sr(mythread)%overflow) then
1161 call kdtree2_sort_results(nfound, results)
1162 endif
1163
1164 return
1165 end subroutine kdtree2_r_nearest
1166
1167 subroutine kdtree2_r_nearest_around_point(tp,idxin,correltime,r2,&
1168 nfound,nalloc,results)
1169 !:Purpose: Like kdtree2_r_nearest, but around a point 'idxin' already existing
1170 ! in the data set.
1171 !
1172 ! Results are NOT sorted unless tree was created with sort option.
1173 !
1174 type (kdtree2), pointer :: tp
1175 integer, intent (In) :: idxin, correltime, nalloc
1176 real(kdkind), intent(in) :: r2
1177 integer, intent(out) :: nfound
1178 type(kdtree2_result), target :: results(:)
1179 integer :: mythread
1180 integer, external :: omp_get_thread_num
1181 ! ..
1182 ! .. Intrinsic Functions ..
1183 intrinsic HUGE
1184 ! ..
1185
1186 mythread = omp_get_thread_num()
1187
1188 allocate (sr(mythread)%qv(tp%dimen))
1189 sr(mythread)%qv = tp%the_data(:,idxin) ! copy the vector
1190 sr(mythread)%ballsize = r2
1191 sr(mythread)%nn = 0 ! flag for fixed r search
1192 sr(mythread)%nfound = 0
1193 sr(mythread)%centeridx = idxin
1194 sr(mythread)%correltime = correltime
1195
1196 sr(mythread)%results => results
1197
1198 sr(mythread)%nalloc = nalloc
1199 sr(mythread)%overflow = .false.
1200
1201 call validate_query_storage(nalloc)
1202
1203 ! sr(mythread)%dsl = HUGE(sr(mythread)%dsl) ! set to huge positive values
1204 ! sr(mythread)%il = -1 ! set to invalid indexes
1205
1206 sr(mythread)%ind => tp%ind
1207 sr(mythread)%rearrange = tp%rearrange
1208
1209 if (tp%rearrange) then
1210 sr(mythread)%Data => tp%rearranged_data
1211 else
1212 sr(mythread)%Data => tp%the_data
1213 endif
1214 sr(mythread)%rearrange = tp%rearrange
1215 sr(mythread)%dimen = tp%dimen
1216
1217 !
1218 !sr(mythread)%dsl = Huge(sr(mythread)%dsl) ! set to huge positive values
1219 !sr(mythread)%il = -1 ! set to invalid indexes
1220 !
1221
1222 call search(tp%root)
1223 nfound = sr(mythread)%nfound
1224 if (tp%sort) then
1225 call kdtree2_sort_results(nfound,results)
1226 endif
1227
1228 if (sr(mythread)%overflow) then
1229 write (*,*) 'KD_TREE_TRANS: warning! return from kdtree2_r_nearest found more neighbors'
1230 write (*,*) 'KD_TREE_TRANS: than storage was provided for. Answer is NOT smallest ball'
1231 write (*,*) 'KD_TREE_TRANS: with that number of neighbors! I.e. it is wrong.'
1232 endif
1233
1234 deallocate (sr(mythread)%qv)
1235 return
1236 end subroutine kdtree2_r_nearest_around_point
1237
1238 function kdtree2_r_count(tp,qv,r2) result(nfound)
1239 !:Purpose: Count the number of neighbors within square distance 'r2'.
1240 type (kdtree2), pointer :: tp
1241 real(kdkind), target, intent (In) :: qv(:)
1242 real(kdkind), intent(in) :: r2
1243 integer :: nfound
1244 integer :: mythread
1245 integer, external :: omp_get_thread_num
1246 ! ..
1247 ! .. Intrinsic Functions ..
1248 intrinsic HUGE
1249 ! ..
1250
1251 mythread = omp_get_thread_num()
1252
1253 sr(mythread)%qv => qv
1254 sr(mythread)%ballsize = r2
1255
1256 sr(mythread)%nn = 0 ! flag for fixed r search
1257 sr(mythread)%nfound = 0
1258 sr(mythread)%centeridx = -1
1259 sr(mythread)%correltime = 0
1260
1261 nullify(sr(mythread)%results) ! for some reason, FTN 95 chokes on '=> null()'
1262
1263 sr(mythread)%nalloc = 0 ! we do not allocate any storage but that's OK
1264 ! for counting.
1265 sr(mythread)%ind => tp%ind
1266 sr(mythread)%rearrange = tp%rearrange
1267 if (tp%rearrange) then
1268 sr(mythread)%Data => tp%rearranged_data
1269 else
1270 sr(mythread)%Data => tp%the_data
1271 endif
1272 sr(mythread)%dimen = tp%dimen
1273
1274 !
1275 !sr(mythread)%dsl = Huge(sr(mythread)%dsl) ! set to huge positive values
1276 !sr(mythread)%il = -1 ! set to invalid indexes
1277 !
1278 sr(mythread)%overflow = .false.
1279
1280 call search(tp%root)
1281
1282 nfound = sr(mythread)%nfound
1283
1284 return
1285 end function kdtree2_r_count
1286
1287 function kdtree2_r_count_around_point(tp,idxin,correltime,r2) &
1288 result(nfound)
1289 !:Purpose: Count the number of neighbors within square distance 'r2' around
1290 ! point 'idxin' with decorrelation time 'correltime'.
1291 !
1292 type (kdtree2), pointer :: tp
1293 integer, intent (In) :: correltime, idxin
1294 real(kdkind), intent(in) :: r2
1295 integer :: nfound
1296 integer :: mythread
1297 integer, external :: omp_get_thread_num
1298 ! ..
1299 ! ..
1300 ! .. Intrinsic Functions ..
1301 intrinsic HUGE
1302 ! ..
1303
1304 mythread = omp_get_thread_num()
1305
1306 allocate (sr(mythread)%qv(tp%dimen))
1307 sr(mythread)%qv = tp%the_data(:,idxin)
1308 sr(mythread)%ballsize = r2
1309
1310 sr(mythread)%nn = 0 ! flag for fixed r search
1311 sr(mythread)%nfound = 0
1312 sr(mythread)%centeridx = idxin
1313 sr(mythread)%correltime = correltime
1314 nullify(sr(mythread)%results)
1315
1316 sr(mythread)%nalloc = 0 ! we do not allocate any storage but that's OK
1317 ! for counting.
1318
1319 sr(mythread)%ind => tp%ind
1320 sr(mythread)%rearrange = tp%rearrange
1321
1322 if (sr(mythread)%rearrange) then
1323 sr(mythread)%Data => tp%rearranged_data
1324 else
1325 sr(mythread)%Data => tp%the_data
1326 endif
1327 sr(mythread)%dimen = tp%dimen
1328
1329 !
1330 !sr(mythread)%dsl = Huge(sr(mythread)%dsl) ! set to huge positive values
1331 !sr(mythread)%il = -1 ! set to invalid indexes
1332 !
1333 sr(mythread)%overflow = .false.
1334
1335 call search(tp%root)
1336
1337 nfound = sr(mythread)%nfound
1338
1339 return
1340 end function kdtree2_r_count_around_point
1341
1342
1343 subroutine validate_query_storage(n)
1344 !:Purpose: make sure we have enough storage for n
1345 integer, intent(in) :: n
1346 integer :: mythread
1347 integer, external :: omp_get_thread_num
1348
1349 mythread = omp_get_thread_num()
1350
1351 if (size(sr(mythread)%results,1) .lt. n) then
1352 call utl_abort('kdtrees_mod-validate_query_storage: not enough storage for results')
1353 endif
1354
1355 return
1356 end subroutine validate_query_storage
1357
1358 function square_distance(d, iv,qv) result (res)
1359 !:Purpose: distance between iv[1:n] and qv[1:n]
1360
1361 ! .. Function Return Value ..
1362 ! re-implemented to improve vectorization.
1363 real(kdkind) :: res
1364 ! ..
1365 ! ..
1366 ! .. Scalar Arguments ..
1367 integer :: d
1368 ! ..
1369 ! .. Array Arguments ..
1370 real(kdkind) :: iv(:),qv(:)
1371 ! ..
1372 ! ..
1373 res = sum( (iv(1:d)-qv(1:d))**2 )
1374 end function square_distance
1375
1376 recursive subroutine search(node)
1377 !:Purpose: This is the innermost core routine of the kd-tree search. Along
1378 ! with "process_terminal_node", it is the performance bottleneck.
1379 !
1380 ! This version uses a logically complete secondary search of
1381 ! "box in bounds", whether the sear
1382 !
1383 type (Tree_node), pointer :: node
1384 ! ..
1385 type(tree_node),pointer :: ncloser, nfarther
1386 !
1387 integer :: cut_dim, i
1388 ! ..
1389 real(kdkind) :: qval, dis
1390 real(kdkind) :: ballsize
1391 real(kdkind), pointer :: qv(:)
1392 type(interval), pointer :: box(:)
1393 integer :: mythread
1394 integer, external :: omp_get_thread_num
1395
1396 mythread = omp_get_thread_num()
1397
1398 if ((associated(node%left) .and. associated(node%right)) .eqv. .false.) then
1399 ! we are on a terminal node
1400 if (sr(mythread)%nn .eq. 0) then
1401 call process_terminal_node_fixedball(node)
1402 else
1403 call process_terminal_node(node)
1404 endif
1405 else
1406 ! we are not on a terminal node
1407 qv => sr(mythread)%qv(1:)
1408 cut_dim = node%cut_dim
1409 qval = qv(cut_dim)
1410
1411 if (qval < node%cut_val) then
1412 ncloser => node%left
1413 nfarther => node%right
1414 dis = (node%cut_val_right - qval)**2
1415! extra = node%cut_val - qval
1416 else
1417 ncloser => node%right
1418 nfarther => node%left
1419 dis = (node%cut_val_left - qval)**2
1420! extra = qval- node%cut_val_left
1421 endif
1422
1423 if (associated(ncloser)) call search(ncloser)
1424
1425 ! we may need to search the second node.
1426 if (associated(nfarther)) then
1427 ballsize = sr(mythread)%ballsize
1428! dis=extra**2
1429 if (dis <= ballsize) then
1430 !
1431 ! we do this separately as going on the first cut dimen is often
1432 ! a good idea.
1433 ! note that if extra**2 < sr(mythread)%ballsize, then the next
1434 ! check will also be false.
1435 !
1436 box => node%box(1:)
1437 do i=1,sr(mythread)%dimen
1438 if (i .ne. cut_dim) then
1439 dis = dis + dis2_from_bnd(qv(i),box(i)%lower,box(i)%upper)
1440 if (dis > ballsize) then
1441 return
1442 endif
1443 endif
1444 end do
1445
1446 !
1447 ! if we are still here then we need to search mroe.
1448 !
1449 call search(nfarther)
1450 endif
1451 endif
1452 end if
1453 end subroutine search
1454
1455
1456 real(kdkind) function dis2_from_bnd(x,amin,amax) result (res)
1457 real(kdkind), intent(in) :: x, amin,amax
1458
1459 if (x > amax) then
1460 res = (x-amax)**2;
1461 return
1462 else
1463 if (x < amin) then
1464 res = (amin-x)**2;
1465 return
1466 else
1467 res = 0.0
1468 return
1469 endif
1470 endif
1471 return
1472 end function dis2_from_bnd
1473
1474 logical function box_in_search_range(node, sr) result(res)
1475 !:Purpose: Return the distance from 'qv' to the CLOSEST corner of node's
1476 ! bounding box for all coordinates outside the box. Coordinates
1477 ! inside the box contribute nothing to the distance.
1478 !
1479 type (tree_node), pointer :: node
1480 type (tree_search_record), pointer :: sr(:)
1481
1482 integer :: dimen, i
1483 real(kdkind) :: dis, ballsize
1484 real(kdkind) :: l, u
1485 integer :: mythread
1486 integer, external :: omp_get_thread_num
1487
1488 mythread = omp_get_thread_num()
1489
1490 dimen = sr(mythread)%dimen
1491 ballsize = sr(mythread)%ballsize
1492 dis = 0.0
1493 res = .true.
1494 do i=1,dimen
1495 l = node%box(i)%lower
1496 u = node%box(i)%upper
1497 dis = dis + (dis2_from_bnd(sr(mythread)%qv(i),l,u))
1498 if (dis > ballsize) then
1499 res = .false.
1500 return
1501 endif
1502 end do
1503 res = .true.
1504 return
1505 end function box_in_search_range
1506
1507
1508 subroutine process_terminal_node(node)
1509 !:Purpose: Look for actual near neighbors in 'node', and update
1510 ! the search results on the sr(:) data structure.
1511 !
1512 type (tree_node), pointer :: node
1513 !
1514 real(kdkind), pointer :: qv(:)
1515 integer, pointer :: ind(:)
1516 real(kdkind), pointer :: data(:,:)
1517 !
1518 integer :: dimen, i, indexofi, k, centeridx, correltime
1519 real(kdkind) :: ballsize, sd, newpri
1520 logical :: rearrange
1521 type(pq), pointer :: pqp
1522 integer :: mythread
1523 integer, external :: omp_get_thread_num
1524
1525 mythread = omp_get_thread_num()
1526
1527 !
1528 ! copy values from sr(:) to local variables
1529 !
1530 !
1531 ! Notice, making local pointers with an EXPLICIT lower bound
1532 ! seems to generate faster code.
1533 ! why? I don't know.
1534 qv => sr(mythread)%qv(1:)
1535 pqp => sr(mythread)%pq
1536 dimen = sr(mythread)%dimen
1537 ballsize = sr(mythread)%ballsize
1538 rearrange = sr(mythread)%rearrange
1539 ind => sr(mythread)%ind(1:)
1540 data => sr(mythread)%Data(1:,1:)
1541 centeridx = sr(mythread)%centeridx
1542 correltime = sr(mythread)%correltime
1543
1544 ! doing_correl = (centeridx >= 0) ! Do we have a decorrelation window?
1545 ! include_point = .true. ! by default include all points
1546 ! search through terminal bucket.
1547
1548 mainloop: do i = node%l, node%u
1549 if (rearrange) then
1550 sd = 0.0
1551 do k = 1,dimen
1552 sd = sd + (data(k,i) - qv(k))**2
1553 if (sd>ballsize) cycle mainloop
1554 end do
1555 indexofi = ind(i) ! only read it if we have not broken out
1556 else
1557 indexofi = ind(i)
1558 sd = 0.0
1559 do k = 1,dimen
1560 sd = sd + (data(k,indexofi) - qv(k))**2
1561 if (sd>ballsize) cycle mainloop
1562 end do
1563 endif
1564
1565 if (centeridx > 0) then ! doing correlation interval?
1566 if (abs(indexofi-centeridx) < correltime) cycle mainloop
1567 endif
1568
1569
1570 !
1571 ! two choices for any point. The list so far is either undersized,
1572 ! or it is not.
1573 !
1574 ! If it is undersized, then add the point and its distance
1575 ! unconditionally. If the point added fills up the working
1576 ! list then set the sr(mythread)%ballsize, maximum distance bound (largest distance on
1577 ! list) to be that distance, instead of the initialized +infinity.
1578 !
1579 ! If the running list is full size, then compute the
1580 ! distance but break out immediately if it is larger
1581 ! than sr(mythread)%ballsize, "best squared distance" (of the largest element),
1582 ! as it cannot be a good neighbor.
1583 !
1584 ! Once computed, compare to best_square distance.
1585 ! if it is smaller, then delete the previous largest
1586 ! element and add the new one.
1587
1588 if (sr(mythread)%nfound .lt. sr(mythread)%nn) then
1589 !
1590 ! add this point unconditionally to fill list.
1591 !
1592 sr(mythread)%nfound = sr(mythread)%nfound +1
1593 newpri = pq_insert(pqp,sd,indexofi)
1594 if (sr(mythread)%nfound .eq. sr(mythread)%nn) ballsize = newpri
1595 ! we have just filled the working list.
1596 ! put the best square distance to the maximum value
1597 ! on the list, which is extractable from the PQ.
1598
1599 else
1600 !
1601 ! now, if we get here,
1602 ! we know that the current node has a squared
1603 ! distance smaller than the largest one on the list, and
1604 ! belongs on the list.
1605 ! Hence we replace that with the current one.
1606 !
1607 ballsize = pq_replace_max(pqp,sd,indexofi)
1608 endif
1609 end do mainloop
1610 !
1611 ! Reset sr(mythread) variables which may have changed during loop
1612 !
1613 sr(mythread)%ballsize = ballsize
1614
1615 end subroutine process_terminal_node
1616
1617 subroutine process_terminal_node_fixedball(node)
1618 !:Purpose: Look for actual near neighbors in 'node', and update
1619 ! the search results on the sr(:) data structure, i.e.
1620 ! save all within a fixed ball.
1621 !
1622 type (tree_node), pointer :: node
1623 !
1624 real(kdkind), pointer :: qv(:)
1625 integer, pointer :: ind(:)
1626 real(kdkind), pointer :: data(:,:)
1627 !
1628 integer :: nfound
1629 integer :: dimen, i, indexofi, k
1630 integer :: centeridx, correltime, nn
1631 real(kdkind) :: ballsize, sd
1632 logical :: rearrange
1633 integer :: mythread
1634 integer, external :: omp_get_thread_num
1635
1636 mythread = omp_get_thread_num()
1637
1638 !
1639 ! copy values from sr(:) to local variables
1640 !
1641 qv => sr(mythread)%qv(1:)
1642 dimen = sr(mythread)%dimen
1643 ballsize = sr(mythread)%ballsize
1644 rearrange = sr(mythread)%rearrange
1645 ind => sr(mythread)%ind(1:)
1646 data => sr(mythread)%Data(1:,1:)
1647 centeridx = sr(mythread)%centeridx
1648 correltime = sr(mythread)%correltime
1649 nn = sr(mythread)%nn ! number to search for
1650 nfound = sr(mythread)%nfound
1651
1652 ! search through terminal bucket.
1653 mainloop: do i = node%l, node%u
1654
1655 !
1656 ! two choices for any point. The list so far is either undersized,
1657 ! or it is not.
1658 !
1659 ! If it is undersized, then add the point and its distance
1660 ! unconditionally. If the point added fills up the working
1661 ! list then set the sr(mythread)%ballsize, maximum distance bound (largest distance on
1662 ! list) to be that distance, instead of the initialized +infinity.
1663 !
1664 ! If the running list is full size, then compute the
1665 ! distance but break out immediately if it is larger
1666 ! than sr(mythread)%ballsize, "best squared distance" (of the largest element),
1667 ! as it cannot be a good neighbor.
1668 !
1669 ! Once computed, compare to best_square distance.
1670 ! if it is smaller, then delete the previous largest
1671 ! element and add the new one.
1672
1673 ! which index to the point do we use?
1674
1675 if (rearrange) then
1676 sd = 0.0
1677 do k = 1,dimen
1678 sd = sd + (data(k,i) - qv(k))**2
1679 if (sd>ballsize) cycle mainloop
1680 end do
1681 indexofi = ind(i) ! only read it if we have not broken out
1682 else
1683 indexofi = ind(i)
1684 sd = 0.0
1685 do k = 1,dimen
1686 sd = sd + (data(k,indexofi) - qv(k))**2
1687 if (sd>ballsize) cycle mainloop
1688 end do
1689 endif
1690
1691 if (centeridx > 0) then ! doing correlation interval?
1692 if (abs(indexofi-centeridx)<correltime) cycle mainloop
1693 endif
1694
1695 nfound = nfound+1
1696 if (nfound .gt. sr(mythread)%nalloc) then
1697 ! oh nuts, we have to add another one to the tree but
1698 ! there isn't enough room.
1699 sr(mythread)%overflow = .true.
1700 else
1701 sr(mythread)%results(nfound)%dis = sd
1702 sr(mythread)%results(nfound)%idx = indexofi
1703 endif
1704 end do mainloop
1705 !
1706 ! Reset sr(mythread) variables which may have changed during loop
1707 !
1708 sr(mythread)%nfound = nfound
1709 end subroutine process_terminal_node_fixedball
1710
1711 subroutine kdtree2_n_nearest_brute_force(tp,qv,nn,results)
1712 !:Purpose: find the 'n' nearest neighbors to 'qv' by exhaustive search.
1713 ! only use this subroutine for testing, as it is SLOW! The
1714 ! whole point of a k-d tree is to avoid doing what this subroutine
1715 ! does.
1716 type (kdtree2), pointer :: tp
1717 real(kdkind), intent (In) :: qv(:)
1718 integer, intent (In) :: nn
1719 type(kdtree2_result) :: results(:)
1720
1721 integer :: i, j, k
1722 real(kdkind), allocatable :: all_distances(:)
1723 ! ..
1724 allocate (all_distances(tp%n))
1725 do i = 1, tp%n
1726 all_distances(i) = square_distance(tp%dimen,qv,tp%the_data(:,i))
1727 end do
1728 ! now find 'n' smallest distances
1729 do i = 1, nn
1730 results(i)%dis = huge(1.0)
1731 results(i)%idx = -1
1732 end do
1733 do i = 1, tp%n
1734 if (all_distances(i)<results(nn)%dis) then
1735 ! insert it somewhere on the list
1736 do j = 1, nn
1737 if (all_distances(i)<results(j)%dis) exit
1738 end do
1739 ! now we know 'j'
1740 do k = nn - 1, j, -1
1741 results(k+1) = results(k)
1742 end do
1743 results(j)%dis = all_distances(i)
1744 results(j)%idx = i
1745 end if
1746 end do
1747 deallocate (all_distances)
1748 end subroutine kdtree2_n_nearest_brute_force
1749
1750
1751 subroutine kdtree2_r_nearest_brute_force(tp,qv,r2,nfound,results)
1752 !:Purpose: find the nearest neighbors to 'qv' with distance**2 <= r2 by exhaustive search.
1753 ! only use this subroutine for testing, as it is SLOW! The
1754 ! whole point of a k-d tree is to avoid doing what this subroutine
1755 ! does.
1756 type (kdtree2), pointer :: tp
1757 real(kdkind), intent (In) :: qv(:)
1758 real(kdkind), intent (In) :: r2
1759 integer, intent(out) :: nfound
1760 type(kdtree2_result) :: results(:)
1761
1762 integer :: i, nalloc
1763 real(kdkind), allocatable :: all_distances(:)
1764 ! ..
1765 allocate (all_distances(tp%n))
1766 do i = 1, tp%n
1767 all_distances(i) = square_distance(tp%dimen,qv,tp%the_data(:,i))
1768 end do
1769
1770 nfound = 0
1771 nalloc = size(results,1)
1772
1773 do i = 1, tp%n
1774 if (all_distances(i)< r2) then
1775 ! insert it somewhere on the list
1776 if (nfound .lt. nalloc) then
1777 nfound = nfound+1
1778 results(nfound)%dis = all_distances(i)
1779 results(nfound)%idx = i
1780 endif
1781 end if
1782 enddo
1783 deallocate (all_distances)
1784
1785 call kdtree2_sort_results(nfound,results)
1786
1787
1788 end subroutine kdtree2_r_nearest_brute_force
1789
1790 subroutine kdtree2_sort_results(nfound,results)
1791 !:Purpose: Use after search to sort results(1:nfound) in order of increasing
1792 ! distance.
1793 integer, intent(in) :: nfound
1794 type(kdtree2_result), target :: results(:)
1795 !
1796 !
1797
1798 !THIS IS BUGGY WITH INTEL FORTRAN
1799 ! If (nfound .Gt. 1) Call heapsort(results(1:nfound)%dis,results(1:nfound)%ind,nfound)
1800 !
1801 if (nfound .gt. 1) call heapsort_struct(results,nfound)
1802
1803 return
1804 end subroutine kdtree2_sort_results
1805
1806 subroutine heapsort(a,ind,n)
1807 !:Purpose: Sort a(1:n) in ascending order, permuting ind(1:n) similarly.
1808 !
1809 ! If ind(k) = k upon input, then it will give a sort index upon output.
1810 !
1811 integer,intent(in) :: n
1812 real(kdkind), intent(inout) :: a(:)
1813 integer, intent(inout) :: ind(:)
1814
1815 !
1816 !
1817 real(kdkind) :: value ! temporary for a value from a()
1818 integer :: ivalue ! temporary for a value from ind()
1819
1820 integer :: i,j
1821 integer :: ileft,iright
1822
1823 ileft=n/2+1
1824 iright=n
1825
1826 ! do i=1,n
1827 ! ind(i)=i
1828 ! Generate initial idum array
1829 ! end do
1830
1831 if(n.eq.1) return
1832
1833 do
1834 if(ileft > 1)then
1835 ileft=ileft-1
1836 value=a(ileft); ivalue=ind(ileft)
1837 else
1838 value=a(iright); ivalue=ind(iright)
1839 a(iright)=a(1); ind(iright)=ind(1)
1840 iright=iright-1
1841 if (iright == 1) then
1842 a(1)=value;ind(1)=ivalue
1843 return
1844 endif
1845 endif
1846 i=ileft
1847 j=2*ileft
1848 do while (j <= iright)
1849 if(j < iright) then
1850 if(a(j) < a(j+1)) j=j+1
1851 endif
1852 if(value < a(j)) then
1853 a(i)=a(j); ind(i)=ind(j)
1854 i=j
1855 j=j+j
1856 else
1857 j=iright+1
1858 endif
1859 end do
1860 a(i)=value; ind(i)=ivalue
1861 end do
1862 end subroutine heapsort
1863
1864 subroutine heapsort_struct(a,n)
1865 !:Purpose: Sort a(1:n) in ascending order
1866 !
1867 integer,intent(in) :: n
1868 type(kdtree2_result),intent(inout) :: a(:)
1869
1870 !
1871 !
1872 type(kdtree2_result) :: value ! temporary value
1873
1874 integer :: i,j
1875 integer :: ileft,iright
1876
1877 ileft=n/2+1
1878 iright=n
1879
1880 ! do i=1,n
1881 ! ind(i)=i
1882 ! Generate initial idum array
1883 ! end do
1884
1885 if(n.eq.1) return
1886
1887 do
1888 if(ileft > 1)then
1889 ileft=ileft-1
1890 value=a(ileft)
1891 else
1892 value=a(iright)
1893 a(iright)=a(1)
1894 iright=iright-1
1895 if (iright == 1) then
1896 a(1) = value
1897 return
1898 endif
1899 endif
1900 i=ileft
1901 j=2*ileft
1902 do while (j <= iright)
1903 if(j < iright) then
1904 if(a(j)%dis < a(j+1)%dis) j=j+1
1905 endif
1906 if(value%dis < a(j)%dis) then
1907 a(i)=a(j);
1908 i=j
1909 j=j+j
1910 else
1911 j=iright+1
1912 endif
1913 end do
1914 a(i)=value
1915 end do
1916 end subroutine heapsort_struct
1917
1918 !--------------------------------------------------------------------------
1919 ! kdtree2_3dPosition
1920 !--------------------------------------------------------------------------
1921 function kdtree2_3dPosition(lon_rad, lat_rad) result(positionArray)
1922 !
1923 !:Purpose: Calculate the 3 dimensional coordinates of a point
1924 ! on the sphere of Earth radius given
1925 ! the longitude-latitude position on the surface of the sphere
1926 ! in radian.
1927 !
1928 implicit none
1929
1930 ! arguments
1931 real(kdkind) :: positionArray(3) ! returned values of function
1932 real(8), intent(in) :: lon_rad, lat_rad
1933
1934 positionArray(1) = ec_ra * sin(lon_rad) * cos(lat_rad)
1935 positionArray(2) = ec_ra * cos(lon_rad) * cos(lat_rad)
1936 positionArray(3) = ec_ra * sin(lat_rad)
1937
1938 end function kdtree2_3dPosition
1939
1940end module kdTree2_mod