FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
bucket_search.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2019 FrontISTR Commons
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
8  use hecmw
9  implicit none
10 
11  private
12  public :: bucketdb
13  public :: bucketdb_init
14  public :: bucketdb_finalize
15  public :: bucketdb_setup
16  public :: bucketdb_getbucketid
17  public :: bucketdb_registerpre
18  public :: bucketdb_allocate
19  public :: bucketdb_register
20  public :: bucketdb_getnumcand
21  public :: bucketdb_getcand
22 
23  integer(kind=kint), parameter :: DEBUG = 0
24 
26  type bucket
27  integer(kind=kint) :: n
28  integer(kind=kint) :: n_max
29  integer(kind=kint), pointer :: member(:) => null()
30  end type bucket
31 
33  type bucketdb
34  private
35  real(kind=kreal) :: x_min(3)
36  real(kind=kreal) :: x_max(3)
37  real(kind=kreal) :: d(3)
38  integer(kind=kint) :: ndiv(3)
39  type(bucket), pointer :: buckets(:,:,:) => null()
40  integer(kind=kint) :: n_tot
41  integer(kind=kint), pointer :: member_all(:) => null()
42  end type bucketdb
43 
44 contains
45 
47  subroutine assert(cond, mesg)
48  implicit none
49  logical, intent(in) :: cond
50  character(len=*) :: mesg
51  if (debug > 0) then
52  if (.not. cond) then
53  write(0,*) 'ASSERTION FAILED: ',mesg
54  call hecmw_abort( hecmw_comm_get_comm() )
55  endif
56  endif
57  end subroutine assert
58 
59 !!!
60 !!! routines for type(bucket)
61 !!!
62 
64  subroutine bucket_init(bkt)
65  implicit none
66  type(bucket), intent(inout) :: bkt
67  bkt%n = 0
68  bkt%n_max = 0
69  nullify(bkt%member)
70  end subroutine bucket_init
71 
73  subroutine bucket_finalize(bkt)
74  implicit none
75  type(bucket), intent(inout) :: bkt
76  !if (bkt%n > 0) deallocate(bkt%member)
77  nullify(bkt%member)
78  bkt%n = 0
79  bkt%n_max = 0
80  end subroutine bucket_finalize
81 
83  subroutine bucket_incr_count(bkt)
84  implicit none
85  type(bucket), intent(inout) :: bkt
86  !$omp atomic
87  bkt%n = bkt%n + 1
88  end subroutine bucket_incr_count
89 
91  subroutine bucket_assign(bkt, mem)
92  implicit none
93  type(bucket), intent(inout) :: bkt
94  integer(kind=kint), pointer :: mem(:)
95  bkt%member => mem
96  bkt%n_max = bkt%n
97  bkt%n = 0
98  end subroutine bucket_assign
99 
101  subroutine bucket_register(bkt, sid)
102  implicit none
103  type(bucket), intent(inout) :: bkt
104  integer(kind=kint), intent(in) :: sid
105  integer(kind=kint) :: idx
106  !$omp atomic capture
107  bkt%n = bkt%n + 1
108  idx = bkt%n
109  !$omp end atomic
110  call assert(idx <= bkt%n_max, 'bucket_register: too many members')
111  bkt%member(idx) = sid
112  end subroutine bucket_register
113 
115  function bucket_get_n(bkt)
116  implicit none
117  integer(kind=kint) :: bucket_get_n
118  type(bucket), intent(in) :: bkt
119  bucket_get_n = bkt%n
120  end function bucket_get_n
121 
123  subroutine bucket_get_member(bkt, n, memb)
124  implicit none
125  type(bucket), intent(in) :: bkt
126  integer(kind=kint), intent(in) :: n
127  integer(kind=kint), intent(out) :: memb(n)
128  call assert(n == bkt%n, 'bucket_get_member: wrong n')
129  memb(1:n) = bkt%member(1:n)
130  end subroutine bucket_get_member
131 
132 !!!
133 !!! routines for type(bucketDB)
134 !!!
135 
137  subroutine bucketdb_init(bktdb)
138  implicit none
139  type(bucketdb), intent(inout) :: bktdb
140  bktdb%x_min(:) = 0.d0
141  bktdb%x_max(:) = 0.d0
142  bktdb%d(:) = 0.d0
143  bktdb%ndiv(:) = 0
144  nullify(bktdb%buckets)
145  bktdb%n_tot = 0
146  nullify(bktdb%member_all)
147  end subroutine bucketdb_init
148 
150  subroutine bucketdb_finalize(bktdb)
151  implicit none
152  type(bucketdb), intent(inout) :: bktdb
153  integer(kind=kint) :: i, j, k
154  if (bktdb%n_tot > 0) then
155  deallocate(bktdb%member_all)
156  bktdb%n_tot = 0
157  endif
158  if (any(bktdb%ndiv == 0)) then
159  bktdb%ndiv(:) = 0
160  return
161  endif
162  do k = 1, bktdb%ndiv(3)
163  do j = 1, bktdb%ndiv(2)
164  do i = 1, bktdb%ndiv(1)
165  call bucket_finalize(bktdb%buckets(i,j,k))
166  enddo
167  enddo
168  enddo
169  deallocate(bktdb%buckets)
170  bktdb%ndiv(:) = 0
171  end subroutine bucketdb_finalize
172 
174  subroutine bucketdb_setup(bktdb, x_min, x_max, dmin, n_tot)
175  implicit none
176  type(bucketdb), intent(inout) :: bktdb
177  real(kind=kreal), intent(in) :: x_min(3)
178  real(kind=kreal), intent(in) :: x_max(3)
179  real(kind=kreal), intent(in) :: dmin
180  integer(kind=kint), intent(in) :: n_tot
181  real(kind=kreal) :: xrange(3)
182  integer(kind=kint) :: i, j, k
183  real(kind=kreal), parameter :: eps = 1.d-6
184  if (debug >= 1) write(0,*) 'DEBUG: bucketDB_setup', x_min, x_max, dmin, n_tot
185  if (associated(bktdb%buckets)) deallocate(bktdb%buckets)
186  bktdb%x_min(:) = x_min(:)
187  bktdb%x_max(:) = x_max(:)
188  xrange(:) = x_max(:) - x_min(:)
189  call assert(all(xrange > 0.d0), 'bucketDB_setup: invalid x_min, x_max')
190  do i = 1, 3
191  bktdb%ndiv(i) = max(floor(xrange(i) / dmin), 1)
192  bktdb%d(i) = xrange(i) / bktdb%ndiv(i) * (1.d0 + eps)
193  enddo
194  if (debug >= 1) write(0,*) 'DEBUG: bucketDB_setup: ndiv, d: ', bktdb%ndiv, bktdb%d
195  call assert(all(bktdb%d > 0.d0), 'bucketDB_setup: invalid bktdb%d')
196  allocate(bktdb%buckets(bktdb%ndiv(1), bktdb%ndiv(2), bktdb%ndiv(3)), stat=i)
197  if( i /= 0 ) then
198  write(*,*) 'Allocation error: bktdb%buckets', bktdb%ndiv
199  call hecmw_abort(hecmw_comm_get_comm())
200  endif
201  do k = 1, bktdb%ndiv(3)
202  do j = 1, bktdb%ndiv(2)
203  do i = 1, bktdb%ndiv(1)
204  call bucket_init(bktdb%buckets(i,j,k))
205  enddo
206  enddo
207  enddo
208  if (bktdb%n_tot /= n_tot) then
209  if (associated(bktdb%member_all)) deallocate(bktdb%member_all)
210  allocate(bktdb%member_all(n_tot))
211  bktdb%n_tot = n_tot
212  endif
213  end subroutine bucketdb_setup
214 
216  function encode_bid(bktdb, baddr)
217  implicit none
218  integer(kind=kint) :: encode_bid
219  type(bucketdb), intent(in) :: bktdb
220  integer(kind=kint), intent(in) :: baddr(3)
221  if (any(baddr <= 0) .or. any(baddr > bktdb%ndiv)) then
222  encode_bid = -1
223  else
224  encode_bid = &
225  (baddr(3)-1) * bktdb%ndiv(1) * bktdb%ndiv(2) + (baddr(2)-1) * bktdb%ndiv(1) + baddr(1)
226  endif
227  end function encode_bid
228 
230  function decode_bid(bktdb, bid)
231  implicit none
232  integer(kind=kint) :: decode_bid(3)
233  type(bucketdb), intent(in) :: bktdb
234  integer(kind=kint), intent(in) :: bid
235  call assert(bid <= bktdb%ndiv(1)*bktdb%ndiv(2)*bktdb%ndiv(3), 'decode_bid: out of range')
236  if (bid < 0) then
237  decode_bid(:) = -1
238  else
239  decode_bid(1) = mod(bid-1, bktdb%ndiv(1)) + 1
240  decode_bid(2) = mod((bid-1)/bktdb%ndiv(1), bktdb%ndiv(2)) + 1
241  decode_bid(3) = (bid-1)/(bktdb%ndiv(1) * bktdb%ndiv(2)) + 1
242  call assert(encode_bid(bktdb, decode_bid) == bid, 'decode_bid')
243  endif
244  end function decode_bid
245 
247  function bucketdb_getbucketid(bktdb, x)
248  implicit none
249  integer(kind=kint) :: bucketdb_getbucketid
250  type(bucketdb), intent(in) :: bktdb
251  real(kind=kreal), intent(in) :: x(3)
252  integer(kind=kint) :: baddr(3)
253  integer(kind=kint) :: i
254  if (bktdb%n_tot == 0) then
256  return
257  endif
258  do i = 1, 3
259  call assert(bktdb%d(i) > 0.d0, 'bucketDB_getBucketID: bktdb%d(i) is zero')
260  baddr(i) = floor((x(i) - bktdb%x_min(i)) / bktdb%d(i)) + 1
261  enddo
262  if (debug >= 2) write(0,*) ' DEBUG: bucketDB_getBucketID: ',x,baddr
263  bucketdb_getbucketid = encode_bid(bktdb, baddr)
264  end function bucketdb_getbucketid
265 
268  subroutine bucketdb_registerpre(bktdb, bid)
269  implicit none
270  type(bucketdb), intent(inout) :: bktdb
271  integer(kind=kint), intent(in) :: bid
272  integer(kind=kint) :: baddr(3)
273  baddr = decode_bid(bktdb, bid)
274  call assert(all(baddr > 0) .and. all(baddr <= bktdb%ndiv), 'bucketDB_register_pre: block ID out of range')
275  call bucket_incr_count(bktdb%buckets(baddr(1),baddr(2),baddr(3)))
276  if (debug >= 2) write(0,*) ' DEBUG: bucketDB_registerPre: ', baddr
277  end subroutine bucketdb_registerpre
278 
281  subroutine bucketdb_allocate(bktdb)
282  implicit none
283  type(bucketdb), intent(inout) :: bktdb
284  integer(kind=kint) :: i, j, k, count, n
285  integer(kind=kint), pointer :: pmemb(:)
286  count = 0
287  do k = 1, bktdb%ndiv(3)
288  do j = 1, bktdb%ndiv(2)
289  do i = 1, bktdb%ndiv(1)
290  !call bucket_allocate(bktdb%buckets(i,j,k))
291  n = bucket_get_n(bktdb%buckets(i,j,k))
292  pmemb => bktdb%member_all(count+1:count+n)
293  call bucket_assign(bktdb%buckets(i,j,k), pmemb)
294  count = count + n
295  enddo
296  enddo
297  enddo
298  end subroutine bucketdb_allocate
299 
302  subroutine bucketdb_register(bktdb, bid, sid)
303  implicit none
304  type(bucketdb), intent(inout) :: bktdb
305  integer(kind=kint), intent(in) :: bid
306  integer(kind=kint), intent(in) :: sid
307  integer(kind=kint) :: baddr(3)
308  baddr = decode_bid(bktdb, bid)
309  call assert(all(baddr > 0) .and. all(baddr <= bktdb%ndiv), 'bucketDB_register: block ID our of range')
310  call bucket_register(bktdb%buckets(baddr(1),baddr(2),baddr(3)), sid)
311  if (debug >= 2) write(0,*) ' DEBUG: bucketDB_register: ', baddr, sid
312  end subroutine bucketdb_register
313 
316  function bucketdb_getnumcand(bktdb, bid)
317  implicit none
318  integer(kind=kint) :: bucketdb_getnumcand
319  type(bucketdb), intent(in) :: bktdb
320  integer(kind=kint), intent(in) :: bid
321  integer(kind=kint) :: baddr(3), ncand, i, j, k, is, ie, js, je, ks, ke
322  if (bid < 0) then
324  return
325  endif
326  baddr = decode_bid(bktdb, bid)
327  ncand = 0
328  is = max(baddr(1)-1, 1)
329  ie = min(baddr(1)+1, bktdb%ndiv(1))
330  js = max(baddr(2)-1, 1)
331  je = min(baddr(2)+1, bktdb%ndiv(2))
332  ks = max(baddr(3)-1, 1)
333  ke = min(baddr(3)+1, bktdb%ndiv(3))
334  do k = ks, ke
335  do j = js, je
336  do i = is, ie
337  ncand = ncand + bucket_get_n(bktdb%buckets(i,j,k))
338  enddo
339  enddo
340  enddo
341  bucketdb_getnumcand = ncand
342  if (debug >= 2) write(0,*) ' DEBUG: bucketDB_getNumCand: ',ncand
343  end function bucketdb_getnumcand
344 
347  subroutine bucketdb_getcand(bktdb, bid, ncand, cand)
348  implicit none
349  type(bucketdb), intent(in) :: bktdb
350  integer(kind=kint), intent(in) :: bid
351  integer(kind=kint), intent(in) :: ncand
352  integer(kind=kint), intent(out), target :: cand(ncand)
353  integer(kind=kint) :: baddr(3), i, j, k, n, cnt, is, ie, js, je, ks, ke
354  integer(kind=kint), pointer :: pcand(:)
355  if (bid < 0 .or. ncand == 0) return
356  baddr = decode_bid(bktdb, bid)
357  cnt = 0
358  is = max(baddr(1)-1, 1)
359  ie = min(baddr(1)+1, bktdb%ndiv(1))
360  js = max(baddr(2)-1, 1)
361  je = min(baddr(2)+1, bktdb%ndiv(2))
362  ks = max(baddr(3)-1, 1)
363  ke = min(baddr(3)+1, bktdb%ndiv(3))
364  do k = ks, ke
365  do j = js, je
366  do i = is, ie
367  n = bucket_get_n(bktdb%buckets(i,j,k))
368  pcand => cand(cnt+1:cnt+n)
369  call bucket_get_member(bktdb%buckets(i,j,k), n, pcand)
370  cnt = cnt + n
371  call assert(cnt <= ncand, 'bucketDB_get_cand: array overflow')
372  enddo
373  enddo
374  enddo
375  call assert(cnt == ncand, 'bucketDB_get_cand: count mismatch')
376  if (debug >= 3) write(0,*) ' DEBUG: bucketDB_getCand: ',cand
377  end subroutine bucketdb_getcand
378 
379 end module bucket_search
This module provides bucket-search functionality It provides definition of bucket info and its access...
subroutine, public bucketdb_allocate(bktdb)
Allocate memory before actually registering members Before allocating memory, bucketDB_registerPre ha...
subroutine, public bucketdb_registerpre(bktdb, bid)
Pre-register for just counting members to be actually registered Bucket ID has to be obtained with bu...
integer(kind=kint) function, public bucketdb_getbucketid(bktdb, x)
Get bucket ID that includes given point.
subroutine, public bucketdb_register(bktdb, bid, sid)
Register member Before actually register, bucketDB_allocate has to be called.
subroutine, public bucketdb_finalize(bktdb)
Finalizer.
integer(kind=kint) function, public bucketdb_getnumcand(bktdb, bid)
Get number of candidates within neighboring buckets of a given bucket Bucket ID has to be obtained wi...
subroutine, public bucketdb_init(bktdb)
Initializer.
subroutine, public bucketdb_getcand(bktdb, bid, ncand, cand)
Get candidates within neighboring buckets of a given bucket Number of candidates has to be obtained w...
subroutine, public bucketdb_setup(bktdb, x_min, x_max, dmin, n_tot)
Setup basic info of buckets.
Definition: hecmw.f90:6