ADflow  v1.0
ADflow is a finite volume RANS solver tailored for gradient-based aerodynamic design optimization.
adtBuild.F90
Go to the documentation of this file.
1 module adtbuild
2  !
3  ! Module which contains all the subroutines for the building of
4  ! an ADT, both surface and volume.
5  !
6  use constants
7  use adtutils, only: adtleaftype, adts, stack, nstack, adtterminate, &
9  use adtdata, only: adttype
10  implicit none
11 
12  !=================================================================
13 
14 contains
15 
16  !===============================================================
17 
18  subroutine buildadt(ADT)
19  !
20  ! This routine builds the 6 dimensional ADT for the given
21  ! ADT. When this routine is called it is assumed that the
22  ! bounding boxes of the grid have already been computed; the
23  ! ADT for these bounding boxes is built here.
24  ! Subroutine intent(inout) arguments.
25  ! --------------------------------
26  ! ADT: adt derived type to build
27  !
28  implicit none
29  !
30  ! Subroutine arguments.
31  !
32  type(adttype), intent(inout) :: ADT
33  !
34  ! Local variables.
35  !
36  integer :: ierr
37 
38  integer(kind=intType) :: i, j, k, ii, kk, ll, mm, nn, nfl, nfr
39  integer(kind=intType) :: nLeaves, nBBoxes, splitDir
40  integer(kind=intType) :: nLeavesToDivide, nLeavesToDivideNew
41  integer(kind=intType) :: nLeavesTot
42 
43  integer(kind=intType), dimension(:), pointer :: BB_IDs
44  integer(kind=intType), dimension(:), pointer :: BB_IDsNew
45  integer(kind=intType), dimension(:), pointer :: nBB_IDs
46  integer(kind=intType), dimension(:), pointer :: nBB_IDsNew
47  integer(kind=intType), dimension(:), pointer :: curLeaf
48  integer(kind=intType), dimension(:), pointer :: curLeafNew
49  integer(kind=intType), dimension(:), pointer :: tmpIntPointer
50 
51  integer(kind=intType), dimension(0:ADT%nProcs - 1) :: tmpArr
52 
53  real(kind=realtype), dimension(:, :), pointer :: xbbox
54 
55  real(kind=realtype), dimension(3, 2) :: rootleafbbox
56  real(kind=realtype), dimension(3, 2, 0:ADT%nProcs - 1) :: &
57  rootleavesbbox
58 
59  type(adtleaftype), dimension(:), pointer :: adtree
60 
61  ! Initialize nStack and allocate the corresponding array stack.
62  ! These are used in the qsort routine for the bounding boxes.
63  ! As this routine is called quite often it is more efficient to
64  ! have the stack array available rather than allocate it over
65  ! and over again.
66 
67  nstack = 100
68  allocate (stack(nstack), stat=ierr)
69  if (ierr /= 0) &
70  call adtterminate(adt, "buildADT", &
71  "Memory allocation failure for stack.")
72 
73  ! Determine the number of leaves of the adt. It can be proved
74  ! that nLeaves equals nBBoxes - 1 for an optimally balanced
75  ! tree. Take the exceptional case of nBBoxes == 0 and
76  ! nBBoxes == 1 into account.
77 
78  nbboxes = adt%nBBoxes
79  nleaves = nbboxes - 1
80  if (nbboxes <= 1) nleaves = nleaves + 1
81 
82  adt%nLeaves = nleaves
83 
84  ! Allocate the memory for the adt.
85 
86  allocate (adt%ADTree(nleaves), stat=ierr)
87  if (ierr /= 0) &
88  call adtterminate(adt, "buildADT", &
89  "Memory allocation failure for ADTree.")
90 
91  ! Set some pointers to make the code more readable.
92 
93  xbbox => adt%xBBox
94  adtree => adt%ADTree
95 
96  ! Allocate the memory for the arrays which control the
97  ! subdivision of the leaves.
98 
99  nn = (nbboxes + 1) / 2
100  nn = max(nn, 1_inttype)
101 
102  allocate (bb_ids(nbboxes), bb_idsnew(nbboxes), &
103  nbb_ids(0:nn), nbb_idsnew(0:nn), &
104  curleaf(nn), curleafnew(nn), stat=ierr)
105  if (ierr /= 0) &
106  call adtterminate(adt, "buildADT", &
107  "Memory allocation failure for the arrays &
108  &used in the subdivision.")
109 
110  ! Initialize the arrays BB_IDs, nBB_IDs and curLeaf, such that
111  ! all bounding boxes belong to the root leaf. Also set the
112  ! counters nLeavesToDivide and nLeavesTot, depending on the
113  ! situation
114 
115  nbb_ids(0) = 0; nbb_ids(1) = nbboxes
116  curleaf(1) = 1
117 
118  do i = 1, nbboxes
119  bb_ids(i) = i
120  end do
121 
122  nleavestodivide = min(nleaves, 1_inttype)
123  nleavestot = nleavestodivide
124 
125  ! Initialize splitDir to 0, such that the first time it will
126  ! split in direction 1.
127 
128  splitdir = 0
129 
130  ! Loop to subdivide the leaves. The division is such that the
131  ! adt is optimally balanced.
132 
133  leafdivision: do
134 
135  ! Criterion to exit the loop.
136 
137  if (nleavestodivide == 0) exit
138 
139  ! Initializations for the next round of subdivisions and
140  ! increment splitDir.
141 
142  nleavestodividenew = 0
143  nbb_idsnew(0) = 0
144 
145  splitdir = splitdir + 1
146  if (splitdir > 6) splitdir = 1
147 
148  ! Loop over the current number of leaves to be divided.
149 
150  currentleavesloop: do i = 1, nleavestodivide
151 
152  ! Store the number of bounding boxes present in the leaf
153  ! in nn, the current leaf number in mm and i-1 in ii.
154 
155  ii = i - 1
156  nn = nbb_ids(i) - nbb_ids(ii)
157  mm = curleaf(i)
158 
159  ! Determine the bounding box coordinates of this leaf.
160 
161  ll = bb_ids(nbb_ids(ii) + 1)
162  adtree(mm)%xMin(1) = xbbox(1, ll)
163  adtree(mm)%xMin(2) = xbbox(2, ll)
164  adtree(mm)%xMin(3) = xbbox(3, ll)
165  adtree(mm)%xMin(4) = xbbox(4, ll)
166  adtree(mm)%xMin(5) = xbbox(5, ll)
167  adtree(mm)%xMin(6) = xbbox(6, ll)
168 
169  adtree(mm)%xMax(1) = xbbox(1, ll)
170  adtree(mm)%xMax(2) = xbbox(2, ll)
171  adtree(mm)%xMax(3) = xbbox(3, ll)
172  adtree(mm)%xMax(4) = xbbox(4, ll)
173  adtree(mm)%xMax(5) = xbbox(5, ll)
174  adtree(mm)%xMax(6) = xbbox(6, ll)
175 
176  do j = (nbb_ids(ii) + 2), nbb_ids(i)
177  ll = bb_ids(j)
178 
179  adtree(mm)%xMin(1) = min(adtree(mm)%xMin(1), xbbox(1, ll))
180  adtree(mm)%xMin(2) = min(adtree(mm)%xMin(2), xbbox(2, ll))
181  adtree(mm)%xMin(3) = min(adtree(mm)%xMin(3), xbbox(3, ll))
182  adtree(mm)%xMin(4) = min(adtree(mm)%xMin(4), xbbox(4, ll))
183  adtree(mm)%xMin(5) = min(adtree(mm)%xMin(5), xbbox(5, ll))
184  adtree(mm)%xMin(6) = min(adtree(mm)%xMin(6), xbbox(6, ll))
185 
186  adtree(mm)%xMax(1) = max(adtree(mm)%xMax(1), xbbox(1, ll))
187  adtree(mm)%xMax(2) = max(adtree(mm)%xMax(2), xbbox(2, ll))
188  adtree(mm)%xMax(3) = max(adtree(mm)%xMax(3), xbbox(3, ll))
189  adtree(mm)%xMax(4) = max(adtree(mm)%xMax(4), xbbox(4, ll))
190  adtree(mm)%xMax(5) = max(adtree(mm)%xMax(5), xbbox(5, ll))
191  adtree(mm)%xMax(6) = max(adtree(mm)%xMax(6), xbbox(6, ll))
192  end do
193 
194  ! Determine the situation of the leaf. It is either a
195  ! terminal leaf or a leaf that must be subdivided.
196 
197  terminaltest: if (nn <= 2) then
198 
199  ! Terminal leaf. Store the ID's of the bounding boxes with
200  ! negative numbers in children.
201 
202  adtree(mm)%children(1) = -bb_ids(nbb_ids(ii) + 1)
203  adtree(mm)%children(2) = -bb_ids(nbb_ids(i))
204 
205  else terminaltest
206 
207  ! Leaf must be divided. Sort the bounding boxes of the
208  ! current leaf in increasing order; the sorting is based
209  ! on the coordinate in the split direction.
210 
211  call qsortbboxes(bb_ids(nbb_ids(ii) + 1:), nn, adt, splitdir)
212 
213  ! Determine the number of bounding boxes in the left leaf.
214  ! This number is at least 2. The actual number stored in
215  ! kk is this number plus an offset. Also initialize the
216  ! counter nfl, which is used to store the bounding boxes
217  ! in the arrays for the new round.
218 
219  kk = (nn + 1) / 2 + nbb_ids(ii)
220  nfl = nbb_idsnew(nleavestodividenew)
221 
222  ! Copy the ID's of the left bounding boxes into BB_IDsNew.
223  ! Also update nLeavesToDivideNew and the corresponding
224  ! entry in nBB_IDsNew.
225 
226  do k = (nbb_ids(ii) + 1), kk
227  nfl = nfl + 1
228  bb_idsnew(nfl) = bb_ids(k)
229  end do
230 
231  nleavestodividenew = nleavestodividenew + 1
232  nbb_idsnew(nleavestodividenew) = nfl
233 
234  ! Update the total number of leaves and store this number
235  ! in child 1 of the current leaf and in the current leaves
236  ! for the next round.
237 
238  nleavestot = nleavestot + 1
239  adtree(mm)%children(1) = nleavestot
240  curleafnew(nleavestodividenew) = nleavestot
241 
242  ! The right leaf will only be created if it has more than
243  ! one bounding box in it, i.e. if the original leaf has
244  ! more than three bounding boxes. If the new leaf only has
245  ! one bounding box in it, it is not created; instead the
246  ! bounding box is stored in the current leaf.
247 
248  if (nn == 3) then
249 
250  ! Only three bounding boxes present in the current leaf.
251  ! The right leaf is not created and the last bounding
252  ! box is stored as the second child of the current leaf.
253 
254  adtree(mm)%children(2) = -bb_ids(nbb_ids(i))
255 
256  else
257 
258  ! More than 3 bounding boxes are present and thus the
259  ! right leaf is created. Copy the ID's from BB_IDs into
260  ! BB_IDsNew and update the counters for the new round.
261 
262  nfr = nbb_idsnew(nleavestodividenew)
263  do k = (kk + 1), nbb_ids(i)
264  nfr = nfr + 1
265  bb_idsnew(nfr) = bb_ids(k)
266  end do
267 
268  nleavestodividenew = nleavestodividenew + 1
269  nbb_idsnew(nleavestodividenew) = nfr
270 
271  ! Update the total number of leaves and store this number
272  ! in child 2 of the current leaf and in the current
273  ! leaves for the next round.
274 
275  nleavestot = nleavestot + 1
276  adtree(mm)%children(2) = nleavestot
277  curleafnew(nleavestodividenew) = nleavestot
278 
279  end if
280 
281  end if terminaltest
282 
283  end do currentleavesloop
284 
285  ! Swap the pointers for the next round.
286 
287  nleavestodivide = nleavestodividenew
288 
289  tmpintpointer => bb_ids
290  bb_ids => bb_idsnew
291  bb_idsnew => tmpintpointer
292 
293  tmpintpointer => nbb_ids
294  nbb_ids => nbb_idsnew
295  nbb_idsnew => tmpintpointer
296 
297  tmpintpointer => curleaf
298  curleaf => curleafnew
299  curleafnew => tmpintpointer
300 
301  end do leafdivision
302 
303  ! Deallocate the arrays used to build the local tree.
304 
305  deallocate (stack, bb_ids, bb_idsnew, nbb_ids, nbb_idsnew, &
306  curleaf, curleafnew, stat=ierr)
307  if (ierr /= 0) &
308  call adtterminate(adt, "buildADT", &
309  "Deallocation failure for the local arrays.")
310  !
311  ! Local tree has been built. Now determine the global
312  ! information for this tree.
313  !
314  ! Determine the number and processor ID's of the non-empty local
315  ! trees by gathering the data from the participating processors.
316 
317  ii = 1
318  if (nbboxes == 0) ii = 0
319 
320  call mpi_allgather(ii, 1, adflow_integer, tmparr, 1, adflow_integer, &
321  adt%comm, ierr)
322 
323  ii = 0
324  do i = 0, (adt%nProcs - 1)
325  ii = ii + tmparr(i)
326  end do
327 
328  adt%nRootLeaves = ii
329 
330  ! Allocate the memory for both the processor ID's and the
331  ! 3D bounding box of the root leaf.
332 
333  allocate (adt%rootLeavesProcs(ii), &
334  adt%rootBBoxes(3, 2, ii), stat=ierr)
335  if (ierr /= 0) &
336  call adtterminate(adt, "buildADT", &
337  "Memory allocation failure for &
338  &rootLeavesProcs and rootBBoxes.")
339 
340  ! Determine the processor ID's of the non-empty trees.
341 
342  ii = 0
343  adt%myEntryInRootProcs = 0
344 
345  do i = 0, (adt%nProcs - 1)
346  if (tmparr(i) > 0) then
347  ii = ii + 1
348  adt%rootLeavesProcs(ii) = i
349  if (adt%myID == i) adt%myEntryInRootProcs = ii
350  end if
351  end do
352 
353  ! Determine the local 3D bounding box of the root leaf.
354  ! If no local tree is present, just set it to zero to avoid
355  ! problems. The values do not matter.
356 
357  if (nbboxes == 0) then
358  rootleafbbox = zero
359  else
360  rootleafbbox(1, 1) = adtree(1)%xMin(1)
361  rootleafbbox(2, 1) = adtree(1)%xMin(2)
362  rootleafbbox(3, 1) = adtree(1)%xMin(3)
363 
364  rootleafbbox(1, 2) = adtree(1)%xMax(4)
365  rootleafbbox(2, 2) = adtree(1)%xMax(5)
366  rootleafbbox(3, 2) = adtree(1)%xMax(6)
367  end if
368 
369  ! Gather the data of the root leaves.
370 
371  call mpi_allgather(rootleafbbox, 6, adflow_real, rootleavesbbox, &
372  6, adflow_real, adt%comm, ierr)
373 
374  ! Store the 3D root bounding boxes of the non-empty trees in
375  ! the data structure for the current ADT.
376 
377  ii = 0
378  do i = 0, (adt%nProcs - 1)
379  if (tmparr(i) > 0) then
380  ii = ii + 1
381 
382  adt%rootBBoxes(1, 1, ii) = rootleavesbbox(1, 1, i)
383  adt%rootBBoxes(2, 1, ii) = rootleavesbbox(2, 1, i)
384  adt%rootBBoxes(3, 1, ii) = rootleavesbbox(3, 1, i)
385 
386  adt%rootBBoxes(1, 2, ii) = rootleavesbbox(1, 2, i)
387  adt%rootBBoxes(2, 2, ii) = rootleavesbbox(2, 2, i)
388  adt%rootBBoxes(3, 2, ii) = rootleavesbbox(3, 2, i)
389  end if
390  end do
391 
392  end subroutine buildadt
393 
394  subroutine buildsurfaceadt(nTria, nQuads, nNodes, &
395  coor, triaConn, quadsConn, &
396  BBox, useBBox, comm, &
397  adtID)
398  !
399  ! This routine builds the 6 dimensional ADT, which stores the
400  ! given surface grid. The memory intensive part of these
401  ! arguments, the arrays with the coordinates and
402  ! connectivities, are not copied. Instead pointers are set to
403  ! these arrays. It is therefore the responsibility of the user
404  ! not to deallocate this memory before all the searches have
405  ! been performed.
406  ! Subroutine intent(in) arguments.
407  ! --------------------------------
408  ! nNodes: Number of local nodes in the given grid.
409  ! nTria: Idem for the triangles.
410  ! nQuads: Idem for the quadrilaterals.
411  ! BBox(3,2): The possible bounding box. Only elements within
412  ! this box will be stored in the ADT.
413  ! useBBox: Whether or not to use the bounding box.
414  ! comm: MPI-communicator for the global ADT.
415  ! adtID: The ID of the ADT.
416  ! Subroutine intent(in), target arguments.
417  ! ----------------------------------------
418  ! coor(3,nNodes): Nodal coordinates of the local grid.
419  ! triaConn(3,nTria): Local connectivity of the triangles.
420  ! quadsConn(4,nQuads): Idem for the quadrilaterals.
421  !
422  implicit none
423  !
424  ! Subroutine arguments.
425  !
426  integer, intent(in) :: comm
427  character(len=*), intent(in) :: adtid
428 
429  integer(kind=intType), intent(in) :: ntria
430  integer(kind=intType), intent(in) :: nquads
431  integer(kind=intType), intent(in) :: nnodes
432 
433  logical, intent(in) :: usebbox
434 
435  integer(kind=intType), dimension(:, :), intent(in), &
436  target :: triaconn
437  integer(kind=intType), dimension(:, :), intent(in), &
438  target :: quadsconn
439 
440  real(kind=realtype), dimension(3, 2), intent(in) :: bbox
441 
442  real(kind=realtype), dimension(:, :), intent(in), &
443  target :: coor
444  !
445  ! Local variables.
446  !
447  integer :: ierr, ll, nnpe, jj
448 
449  integer(kind=adtElementType) :: eltype
450 
451  integer(kind=intType) :: i, j, ii, mm, nn, nelem
452 
453  integer(kind=intType), dimension(:, :), pointer :: conn
454 
455  real(kind=realtype), dimension(3) :: xmin, xmax
456 
457  logical, dimension(:), allocatable :: elementwithinbbox
458 
459  type(adttype), pointer :: ADT
460 
461  ! ! Allocate or reallocate the memory for ADTs. This depends
462  ! ! whether or not this is the first ADT to be built.
463 
464  if (allocated(adts)) then
465  call reallocateadts(adtid, jj)
466  else
467  call allocateadts
468  jj = 1
469  end if
470 
471  ! The ADT we are currently working with
472  adt => adts(jj)
473 
474  ! Make sure the ADT is active and store the ID of this ADT.
475 
476  adt%isActive = .true.
477  adt%adtID = adtid
478 
479  ! Copy the communicator and determine the number of processors
480  ! and my processor ID in this group.
481 
482  adt%comm = comm
483  call mpi_comm_rank(comm, adt%myID, ierr)
484  call mpi_comm_size(comm, adt%nProcs, ierr)
485 
486  ! Set the ADT type, which is a surface ADT.
487 
488  adt%adtType = adtsurfaceadt
489 
490  ! Copy the number of nodes and surface elements and set the
491  ! number of volume elements to 0; only a surface grid has been
492  ! given.
493 
494  adt%nNodes = nnodes
495  adt%nTria = ntria
496  adt%nQuads = nquads
497 
498  adt%nTetra = 0
499  adt%nPyra = 0
500  adt%nPrisms = 0
501  adt%nHexa = 0
502 
503  ! Set the pointers for the coordinates and the
504  ! surface connectivities.
505 
506  adt%coor => coor
507  adt%triaConn => triaconn
508  adt%quadsConn => quadsconn
509 
510  ! Determine the number of elements to be stored in the ADT.
511  ! This depends whether or not the global bounding box should be
512  ! used when building the ADT.
513 
514  testbbox: if (usebbox) then
515 
516  ! Global bounding box is used. Allocate the memory for the
517  ! logical elementWithinBBox.
518 
519  nn = ntria + nquads
520  allocate (elementwithinbbox(nn), stat=ierr)
521  if (ierr /= 0) &
522  call adtterminate(adt, "buildSurfaceADT", &
523  "Memory allocation failure for &
524  &elementWithinBBox.")
525 
526  ! Loop over the number of element types.
527 
528  ii = 0
529  elementloop1: do ll = 1, 2
530 
531  ! Set the correct pointers for this element.
532 
533  call setsurfacepointers(ll)
534 
535  ! Loop over the elements and determine the bounding box of
536  ! each element.
537 
538  do i = 1, nelem
539  ii = ii + 1
540 
541  mm = conn(1, i)
542  xmin(1) = coor(1, mm); xmax(1) = coor(1, mm)
543  xmin(2) = coor(2, mm); xmax(2) = coor(2, mm)
544  xmin(3) = coor(3, mm); xmax(3) = coor(3, mm)
545 
546  do j = 2, nnpe
547  mm = conn(j, i)
548 
549  xmin(1) = min(xmin(1), coor(1, mm))
550  xmin(2) = min(xmin(2), coor(2, mm))
551  xmin(3) = min(xmin(3), coor(3, mm))
552 
553  xmax(1) = max(xmax(1), coor(1, mm))
554  xmax(2) = max(xmax(2), coor(2, mm))
555  xmax(3) = max(xmax(3), coor(3, mm))
556  end do
557 
558  ! Check if the bounding box is (partially) inside the
559  ! global bounding box. If so, set elementWithinBBox
560  ! to .true.; otherwise set it to .false.
561 
562  if (xmax(1) >= bbox(1, 1) .and. xmin(1) <= bbox(1, 2) .and. &
563  xmax(2) >= bbox(2, 1) .and. xmin(2) <= bbox(2, 2) .and. &
564  xmax(3) >= bbox(3, 1) .and. xmin(3) <= bbox(3, 2)) then
565  elementwithinbbox(ii) = .true.
566  else
567  elementwithinbbox(ii) = .false.
568  end if
569 
570  end do
571  end do elementloop1
572 
573  ! Determine the local number of elements within the global
574  ! bounding box.
575 
576  ii = 0
577  do i = 1, nn
578  if (elementwithinbbox(i)) ii = ii + 1
579  end do
580 
581  adt%nBBoxes = ii
582 
583  ! Allocate the memory for the bounding box coordinates, the
584  ! corresponding element type and the index in the connectivity.
585 
586  allocate (adt%xBBox(6, ii), adt%elementType(ii), &
587  adt%elementID(ii), stat=ierr)
588  if (ierr /= 0) &
589  call adtterminate(adt, "buildSurfaceADT", &
590  "Memory allocation failure for bounding &
591  &box data.")
592 
593  ! Repeat the loop over the all the elements, but now store
594  ! the bounding boxes in the ADT.
595 
596  ii = 0
597  nn = 0
598  elementloop2: do ll = 1, 2
599 
600  ! Set the correct pointers for this element.
601 
602  call setsurfacepointers(ll)
603 
604  ! Loop over the elements and store the bounding box info,
605  ! if needed.
606 
607  do i = 1, nelem
608  ii = ii + 1
609  testwithin: if (elementwithinbbox(ii)) then
610 
611  nn = nn + 1
612 
613  adt%elementType(nn) = eltype
614  adt%elementID(nn) = i
615 
616  mm = conn(1, i)
617  xmin(1) = coor(1, mm); xmax(1) = coor(1, mm)
618  xmin(2) = coor(2, mm); xmax(2) = coor(2, mm)
619  xmin(3) = coor(3, mm); xmax(3) = coor(3, mm)
620 
621  do j = 2, nnpe
622  mm = conn(j, i)
623 
624  xmin(1) = min(xmin(1), coor(1, mm))
625  xmin(2) = min(xmin(2), coor(2, mm))
626  xmin(3) = min(xmin(3), coor(3, mm))
627 
628  xmax(1) = max(xmax(1), coor(1, mm))
629  xmax(2) = max(xmax(2), coor(2, mm))
630  xmax(3) = max(xmax(3), coor(3, mm))
631  end do
632 
633  adt%xBBox(1, nn) = xmin(1)
634  adt%xBBox(2, nn) = xmin(2)
635  adt%xBBox(3, nn) = xmin(3)
636 
637  adt%xBBox(4, nn) = xmax(1)
638  adt%xBBox(5, nn) = xmax(2)
639  adt%xBBox(6, nn) = xmax(3)
640 
641  end if testwithin
642  end do
643  end do elementloop2
644 
645  ! Deallocate the memory for elementWithinBBox.
646 
647  deallocate (elementwithinbbox, stat=ierr)
648  if (ierr /= 0) &
649  call adtterminate(adt, "buildSurfaceADT", &
650  "Deallocation failure for &
651  &elementWithinBBox.")
652 
653  else testbbox
654 
655  ! No global bounding box. The number of local bounding boxes
656  ! to be stored is the total number of local surface elements.
657 
658  ii = ntria + nquads
659  adt%nBBoxes = ii
660 
661  ! Allocate the memory for the bounding box coordinates, the
662  ! corresponding element type and the index in the connectivity.
663 
664  allocate (adt%xBBox(6, ii), adt%elementType(ii), &
665  adt%elementID(ii), stat=ierr)
666  if (ierr /= 0) &
667  call adtterminate(adt, "buildSurfaceADT", &
668  "Memory allocation failure for bounding &
669  &box data.")
670 
671  ! Loop over the number of element types present, i.e. 2,
672  ! to store the bounding boxes; nn is the counter.
673 
674  nn = 0
675  elementloop3: do ll = 1, 2
676 
677  ! Set the correct pointers for this element.
678 
679  call setsurfacepointers(ll)
680 
681  ! Loop over the number of elements and store the bounding
682  ! box info.
683 
684  do i = 1, nelem
685  nn = nn + 1
686 
687  adt%elementType(nn) = eltype
688  adt%elementID(nn) = i
689 
690  mm = conn(1, i)
691  xmin(1) = coor(1, mm); xmax(1) = coor(1, mm)
692  xmin(2) = coor(2, mm); xmax(2) = coor(2, mm)
693  xmin(3) = coor(3, mm); xmax(3) = coor(3, mm)
694 
695  do j = 2, nnpe
696  mm = conn(j, i)
697 
698  xmin(1) = min(xmin(1), coor(1, mm))
699  xmin(2) = min(xmin(2), coor(2, mm))
700  xmin(3) = min(xmin(3), coor(3, mm))
701 
702  xmax(1) = max(xmax(1), coor(1, mm))
703  xmax(2) = max(xmax(2), coor(2, mm))
704  xmax(3) = max(xmax(3), coor(3, mm))
705  end do
706 
707  adt%xBBox(1, nn) = xmin(1)
708  adt%xBBox(2, nn) = xmin(2)
709  adt%xBBox(3, nn) = xmin(3)
710 
711  adt%xBBox(4, nn) = xmax(1)
712  adt%xBBox(5, nn) = xmax(2)
713  adt%xBBox(6, nn) = xmax(3)
714  end do
715 
716  end do elementloop3
717 
718  end if testbbox
719 
720  ! Build the ADT from the now known boundary boxes.
721 
722  call buildadt(adt)
723 
724  !===============================================================
725 
726  contains
727 
728  !=============================================================
729 
730  subroutine setsurfacepointers(ll)
731  !
732  ! This internal subroutine sets the pointers to the correct
733  ! surface element, such that a loop over the element types
734  ! can be used.
735  ! Subroutine intent(in) arguments.
736  ! --------------------------------
737  ! ll: Element type for which the pointers must be used.
738  !
739  implicit none
740  !
741  ! Subroutine arguments.
742  !
743  integer, intent(in) :: ll
744 
745  select case (ll)
746  case (1)
747  eltype = adttriangle; nelem = ntria; nnpe = 3
748  conn => triaconn
749  case (2)
750  eltype = adtquadrilateral; nelem = nquads; nnpe = 4
751  conn => quadsconn
752  case (3)
753  end select
754 
755  end subroutine setsurfacepointers
756 
757  end subroutine buildsurfaceadt
758 
759  subroutine buildvolumeadt(nTetra, nPyra, nPrisms, &
760  nHexa, nNodes, coor, &
761  tetraConn, pyraConn, prismsConn, &
762  hexaConn, BBox, useBBox, &
763  comm, adtID)
764  !
765  ! This routine builds the 6 dimensional ADT, which stores the
766  ! given volume grid. The memory intensive part of these
767  ! arguments, the arrays with the coordinates and
768  ! connectivities, are not copied. Instead pointers are set to
769  ! these arrays. It is therefore the responsibility of the user
770  ! not to deallocate this memory before all the searches have
771  ! been performed.
772  ! Subroutine intent(in) arguments.
773  ! --------------------------------
774  ! nNodes: Number of local nodes in the given grid.
775  ! nTetra: Idem for the tetrahedra.
776  ! nPyra: Idem for the pyramids.
777  ! nPrisms: Idem for the prisms.
778  ! nHexa: Idem for the hexahedra.
779  ! BBox(3,2): The possible bounding box. Only elements within
780  ! this box will be stored in the ADT.
781  ! useBBox: Whether or not to use the bounding box.
782  ! comm: MPI-communicator for the global ADT.
783  ! adtID: The ID of the ADT.
784  ! Subroutine intent(in), target arguments.
785  ! ----------------------------------------
786  ! coor(3,nNodes): Nodal coordinates of the local grid.
787  ! tetraConn(4,nTetra): Local connectivity of the tetrahedra.
788  ! pyraConn(5,nPyra): Idem for the pyramids.
789  ! prismsConn(6,nPrisms): Idem for the prisms.
790  ! hexaConn(8,nHexa): Idem for the hexahedra.
791  !
792  implicit none
793  !
794  ! Subroutine arguments.
795  !
796  integer, intent(in) :: comm
797  character(len=*), intent(in) :: adtID
798 
799  integer(kind=intType), intent(in) :: nTetra
800  integer(kind=intType), intent(in) :: nPyra
801  integer(kind=intType), intent(in) :: nPrisms
802  integer(kind=intType), intent(in) :: nHexa
803  integer(kind=intType), intent(in) :: nNodes
804 
805  logical, intent(in) :: useBBox
806 
807  integer(kind=intType), dimension(:, :), intent(in), &
808  target :: tetraConn
809  integer(kind=intType), dimension(:, :), intent(in), &
810  target :: pyraConn
811  integer(kind=intType), dimension(:, :), intent(in), &
812  target :: prismsConn
813  integer(kind=intType), dimension(:, :), intent(in), &
814  target :: hexaConn
815 
816  real(kind=realtype), dimension(3, 2), intent(in) :: bbox
817 
818  real(kind=realtype), dimension(:, :), intent(in), &
819  target :: coor
820  !
821  ! Local variables.
822  !
823  integer :: ierr, ll, nNPE
824 
825  integer(kind=adtElementType) :: elType
826 
827  integer(kind=intType) :: i, j, ii, jj, mm, nn, nElem
828 
829  integer(kind=intType), dimension(:, :), pointer :: conn
830 
831  real(kind=realtype), dimension(3) :: xmin, xmax
832 
833  logical, dimension(:), allocatable :: elementWithinBBox
834 
835  type(adttype), pointer :: ADT
836 
837  ! Allocate or reallocate the memory for ADTs. This depends
838  ! whether or not this is the first ADT to be built.
839 
840  if (allocated(adts)) then
841  call reallocateadts(adtid, jj)
842  else
843  call allocateadts
844  jj = 1
845  end if
846 
847  adt => adts(jj)
848 
849  ! Make sure the ADT is active and store the ID of this ADT.
850 
851  adt%isActive = .true.
852  adt%adtID = adtid
853 
854  ! Copy the communicator and determine the number of processors
855  ! and my processor ID in this group.
856 
857  adt%comm = comm
858  call mpi_comm_rank(comm, adt%myID, ierr)
859  call mpi_comm_size(comm, adt%nProcs, ierr)
860 
861  ! Set the ADT type, which is a volume ADT.
862 
863  adt%adtType = adtvolumeadt
864 
865  ! Copy the number of nodes and volume elements and set the number
866  ! of surface elements to 0; only a volume grid has been given.
867 
868  adt%nNodes = nnodes
869  adt%nTetra = ntetra
870  adt%nPyra = npyra
871  adt%nPrisms = nprisms
872  adt%nHexa = nhexa
873 
874  adt%nTria = 0
875  adt%nQuads = 0
876 
877  ! Set the pointers for the coordinates and the
878  ! volume connectivities.
879 
880  adt%coor => coor
881  adt%tetraConn => tetraconn
882  adt%pyraConn => pyraconn
883  adt%prismsConn => prismsconn
884  adt%hexaConn => hexaconn
885 
886  ! Determine the number of elements to be stored in the ADT.
887  ! This depends whether or not the global bounding box should be
888  ! used when building the ADT.
889 
890  testbbox: if (usebbox) then
891 
892  ! Global bounding box is used. Allocate the memory for the
893  ! logical elementWithinBBox.
894 
895  nn = ntetra + npyra + nprisms + nhexa
896  allocate (elementwithinbbox(nn), stat=ierr)
897  if (ierr /= 0) &
898  call adtterminate(adt, "buildVolumeADT", &
899  "Memory allocation failure for &
900  &elementWithinBBox.")
901 
902  ! Loop over the number of element types.
903 
904  ii = 0
905  elementloop1: do ll = 1, 4
906 
907  ! Set the correct pointers for this element.
908 
909  call setvolumepointers(ll)
910 
911  ! Loop over the elements and determine the bounding box of
912  ! each element.
913 
914  do i = 1, nelem
915  ii = ii + 1
916 
917  mm = conn(1, i)
918  xmin(1) = coor(1, mm); xmax(1) = coor(1, mm)
919  xmin(2) = coor(2, mm); xmax(2) = coor(2, mm)
920  xmin(3) = coor(3, mm); xmax(3) = coor(3, mm)
921 
922  do j = 2, nnpe
923  mm = conn(j, i)
924 
925  xmin(1) = min(xmin(1), coor(1, mm))
926  xmin(2) = min(xmin(2), coor(2, mm))
927  xmin(3) = min(xmin(3), coor(3, mm))
928 
929  xmax(1) = max(xmax(1), coor(1, mm))
930  xmax(2) = max(xmax(2), coor(2, mm))
931  xmax(3) = max(xmax(3), coor(3, mm))
932  end do
933 
934  ! Check if the bounding box is (partially) inside the
935  ! global bounding box. If so, set elementWithinBBox
936  ! to .true.; otherwise set it to .false.
937 
938  if (xmax(1) >= bbox(1, 1) .and. xmin(1) <= bbox(1, 2) .and. &
939  xmax(2) >= bbox(2, 1) .and. xmin(2) <= bbox(2, 2) .and. &
940  xmax(3) >= bbox(3, 1) .and. xmin(3) <= bbox(3, 2)) then
941  elementwithinbbox(ii) = .true.
942  else
943  elementwithinbbox(ii) = .false.
944  end if
945 
946  end do
947  end do elementloop1
948 
949  ! Determine the local number of elements within the global
950  ! bounding box.
951 
952  ii = 0
953  do i = 1, nn
954  if (elementwithinbbox(i)) ii = ii + 1
955  end do
956 
957  adt%nBBoxes = ii
958 
959  ! Allocate the memory for the bounding box coordinates, the
960  ! corresponding element type and the index in the connectivity.
961 
962  allocate (adt%xBBox(6, ii), adt%elementType(ii), &
963  adt%elementID(ii), stat=ierr)
964  if (ierr /= 0) &
965  call adtterminate(adt, "buildVolumeADT", &
966  "Memory allocation failure for bounding &
967  &box data.")
968 
969  ! Repeat the loop over the all the elements, but now store
970  ! the bounding boxes in the ADT.
971 
972  ii = 0
973  nn = 0
974  elementloop2: do ll = 1, 4
975 
976  ! Set the correct pointers for this element.
977 
978  call setvolumepointers(ll)
979 
980  ! Loop over the elements and store the bounding box info,
981  ! if needed.
982 
983  do i = 1, nelem
984  ii = ii + 1
985  testwithin: if (elementwithinbbox(ii)) then
986 
987  nn = nn + 1
988 
989  adt%elementType(nn) = eltype
990  adt%elementID(nn) = i
991 
992  mm = conn(1, i)
993  xmin(1) = coor(1, mm); xmax(1) = coor(1, mm)
994  xmin(2) = coor(2, mm); xmax(2) = coor(2, mm)
995  xmin(3) = coor(3, mm); xmax(3) = coor(3, mm)
996 
997  do j = 2, nnpe
998  mm = conn(j, i)
999 
1000  xmin(1) = min(xmin(1), coor(1, mm))
1001  xmin(2) = min(xmin(2), coor(2, mm))
1002  xmin(3) = min(xmin(3), coor(3, mm))
1003 
1004  xmax(1) = max(xmax(1), coor(1, mm))
1005  xmax(2) = max(xmax(2), coor(2, mm))
1006  xmax(3) = max(xmax(3), coor(3, mm))
1007  end do
1008 
1009  adt%xBBox(1, nn) = xmin(1)
1010  adt%xBBox(2, nn) = xmin(2)
1011  adt%xBBox(3, nn) = xmin(3)
1012 
1013  adt%xBBox(4, nn) = xmax(1)
1014  adt%xBBox(5, nn) = xmax(2)
1015  adt%xBBox(6, nn) = xmax(3)
1016 
1017  end if testwithin
1018  end do
1019  end do elementloop2
1020 
1021  ! Deallocate the memory for elementWithinBBox.
1022 
1023  deallocate (elementwithinbbox, stat=ierr)
1024  if (ierr /= 0) &
1025  call adtterminate(adt, "buildVolumeADT", &
1026  "Deallocation failure for &
1027  &elementWithinBBox.")
1028 
1029  else testbbox
1030 
1031  ! No global bounding box. The number of local bounding boxes
1032  ! to be stored is the total number of local volume elements.
1033 
1034  ii = ntetra + npyra + nprisms + nhexa
1035  adt%nBBoxes = ii
1036 
1037  ! Allocate the memory for the bounding box coordinates, the
1038  ! corresponding element type and the index in the connectivity.
1039 
1040  allocate (adt%xBBox(6, ii), adt%elementType(ii), &
1041  adt%elementID(ii), stat=ierr)
1042  if (ierr /= 0) &
1043  call adtterminate(adt, "buildVolumeADT", &
1044  "Memory allocation failure for bounding &
1045  &box data.")
1046 
1047  ! Loop over the number of element types present, i.e. 4,
1048  ! to store the bounding boxes; nn is the counter.
1049 
1050  nn = 0
1051  elementloop3: do ll = 1, 4
1052 
1053  ! Set the correct pointers for this element.
1054 
1055  call setvolumepointers(ll)
1056 
1057  ! Loop over the number of elements and store the bounding
1058  ! box info.
1059 
1060  do i = 1, nelem
1061  nn = nn + 1
1062 
1063  adt%elementType(nn) = eltype
1064  adt%elementID(nn) = i
1065 
1066  mm = conn(1, i)
1067  xmin(1) = coor(1, mm); xmax(1) = coor(1, mm)
1068  xmin(2) = coor(2, mm); xmax(2) = coor(2, mm)
1069  xmin(3) = coor(3, mm); xmax(3) = coor(3, mm)
1070 
1071  do j = 2, nnpe
1072  mm = conn(j, i)
1073 
1074  xmin(1) = min(xmin(1), coor(1, mm))
1075  xmin(2) = min(xmin(2), coor(2, mm))
1076  xmin(3) = min(xmin(3), coor(3, mm))
1077 
1078  xmax(1) = max(xmax(1), coor(1, mm))
1079  xmax(2) = max(xmax(2), coor(2, mm))
1080  xmax(3) = max(xmax(3), coor(3, mm))
1081  end do
1082 
1083  adt%xBBox(1, nn) = xmin(1)
1084  adt%xBBox(2, nn) = xmin(2)
1085  adt%xBBox(3, nn) = xmin(3)
1086 
1087  adt%xBBox(4, nn) = xmax(1)
1088  adt%xBBox(5, nn) = xmax(2)
1089  adt%xBBox(6, nn) = xmax(3)
1090  end do
1091 
1092  end do elementloop3
1093 
1094  end if testbbox
1095 
1096  ! Build the ADT from the now known boundary boxes.
1097 
1098  call buildadt(adt)
1099 
1100  !===============================================================
1101 
1102  contains
1103 
1104  !=============================================================
1105 
1106  subroutine setvolumepointers(ll)
1107  !
1108  ! This internal subroutine sets the pointers to the correct
1109  ! volume element, such that a loop over the element types
1110  ! can be used.
1111  ! Subroutine intent(in) arguments.
1112  ! --------------------------------
1113  ! ll: Element type for which the pointers must be used.
1114  !
1115  implicit none
1116  !
1117  ! Subroutine arguments.
1118  !
1119  integer, intent(in) :: ll
1120 
1121  select case (ll)
1122  case (1)
1123  eltype = adttetrahedron; nelem = ntetra; nnpe = 4
1124  conn => tetraconn
1125  case (2)
1126  eltype = adtpyramid; nelem = npyra; nnpe = 5
1127  conn => pyraconn
1128  case (3)
1129  eltype = adtprism; nelem = nprisms; nnpe = 6
1130  conn => prismsconn
1131  case (4)
1132  eltype = adthexahedron; nelem = nhexa; nnpe = 8
1133  conn => hexaconn
1134  end select
1135 
1136  end subroutine setvolumepointers
1137 
1138  end subroutine buildvolumeadt
1139 
1140  subroutine buildserialhex(nHexa, nNodes, coor, hexaConn, ADT)
1141  !
1142  ! This a specialized routine that builds and ADT tree for
1143  ! hex volumes only and only in serial. Also, this routine does
1144  ! use adtDats's ADTs() array list...the user must supply the
1145  ! adtType to use and is responsible for all data management of
1146  ! this type.
1147  ! The memory intensive part of these
1148  ! arguments, the arrays with the coordinates and
1149  ! connectivities, are not copied. Instead pointers are set to
1150  ! these arrays. It is therefore the responsibility of the user
1151  ! not to deallocate this memory before all the searches have
1152  ! been performed.
1153  ! Subroutine intent(in) arguments.
1154  ! --------------------------------
1155  ! * nHexa : Number of hexa cells
1156  ! nNodes: Number of nodes in the given grid.
1157  ! Subroutine intent(in), target arguments.
1158  ! ----------------------------------------
1159  ! coor(3,nNodes): Nodal coordinates of the local grid.
1160  ! hexaConn(8,nHexa): Idem for the hexahedra.
1161  ! Subroutine intent(out), arguments.
1162  ! ----------------------------------------
1163  ! ADT : The newly completed ADT
1164  !
1165  implicit none
1166  !
1167  ! Subroutine arguments.
1168  !
1169  integer(kind=intType), intent(in) :: nHexa
1170  integer(kind=intType), intent(in) :: nNodes
1171 
1172  integer(kind=intType), dimension(:, :), intent(in), &
1173  target :: hexaConn
1174 
1175  real(kind=realtype), dimension(:, :), intent(in), &
1176  target :: coor
1177  type(adttype), intent(out) :: adt
1178  !
1179  ! Local variables.
1180  !
1181  integer :: ierr, ll, nnpe
1182  integer(kind=intType) :: i, j, mm
1183  real(kind=realtype), dimension(3) :: xmin, xmax
1184 
1185  ! We need to set comm...explictly mpi_comm_self
1186  adt%comm = mpi_comm_self
1187  adt%nProcs = 1
1188  adt%myID = 0
1189  ! Set the ADT type, which is a volume ADT.
1190 
1191  adt%adtType = adtvolumeadt
1192 
1193  ! Copy the number of nodes and volume elements and set the number
1194  ! of surface elements to 0; only a volume grid has been given.
1195 
1196  adt%nNodes = nnodes
1197  adt%nHexa = nhexa
1198  adt%nTetra = 0
1199  adt%nPyra = 0
1200  adt%nPrisms = 0
1201  adt%nTria = 0
1202  adt%nQuads = 0
1203 
1204  ! Set the pointers for the coordinates and the
1205  ! volume connectivities.
1206 
1207  adt%coor => coor
1208  adt%hexaConn => hexaconn
1209  nullify (adt%tetraConn, adt%pyraConn, adt%prismsConn)
1210 
1211  adt%nBBoxes = nhexa
1212 
1213  ! Allocate the memory for the bounding box coordinates, the
1214  ! corresponding element type and the index in the connectivity.
1215 
1216  allocate (adt%xBBox(6, nhexa))
1217  allocate (adt%elementType(nhexa))
1218  allocate (adt%elementID(nhexa))
1219 
1220  ! All hexas
1221  adt%elementType = adthexahedron
1222 
1223  ! Loop over the number of elements and store the bounding
1224  ! box info.
1225  nnpe = 8
1226 
1227  do i = 1, nhexa
1228 
1229  mm = hexaconn(1, i)
1230  xmin(1) = coor(1, mm); xmax(1) = coor(1, mm)
1231  xmin(2) = coor(2, mm); xmax(2) = coor(2, mm)
1232  xmin(3) = coor(3, mm); xmax(3) = coor(3, mm)
1233 
1234  do j = 2, nnpe
1235  mm = hexaconn(j, i)
1236 
1237  xmin(1) = min(xmin(1), coor(1, mm))
1238  xmin(2) = min(xmin(2), coor(2, mm))
1239  xmin(3) = min(xmin(3), coor(3, mm))
1240 
1241  xmax(1) = max(xmax(1), coor(1, mm))
1242  xmax(2) = max(xmax(2), coor(2, mm))
1243  xmax(3) = max(xmax(3), coor(3, mm))
1244  end do
1245 
1246  adt%xBBox(1, i) = xmin(1)
1247  adt%xBBox(2, i) = xmin(2)
1248  adt%xBBox(3, i) = xmin(3)
1249 
1250  adt%xBBox(4, i) = xmax(1)
1251  adt%xBBox(5, i) = xmax(2)
1252  adt%xBBox(6, i) = xmax(3)
1253 
1254  ! elementID is just sequential since we only have 1 element type
1255  adt%elementID(i) = i
1256 
1257  end do
1258 
1259  ! Build the ADT from the now known boundary boxes.
1260 
1261  call buildadt(adt)
1262 
1263  end subroutine buildserialhex
1264 
1265  subroutine destroyserialhex(ADT)
1266  ! Deallocate the data allocated from the ADT
1267 
1268  implicit none
1269  type(adttype), intent(inout) :: adt
1270 
1271  deallocate (adt%xBBox)
1272  deallocate (adt%elementType)
1273  deallocate (adt%elementID)
1274  deallocate (adt%ADTree)
1275  end subroutine destroyserialhex
1276 
1277  subroutine buildserialquad(nQuad, nNodes, coor, quadsConn, ADT)
1278  !
1279  ! This a specialized routine that builds and ADT tree for
1280  ! quad surface meshes and only in serial. Also, this routine
1281  ! does not
1282  ! use adtDats's ADTs() array list...the user must supply the
1283  ! adtType to use and is responsible for all data management of
1284  ! this type.
1285  ! The memory intensive part of these
1286  ! arguments, the arrays with the coordinates and
1287  ! connectivities, are not copied. Instead pointers are set to
1288  ! these arrays. It is therefore the responsibility of the user
1289  ! not to deallocate this memory before all the searches have
1290  ! been performed.
1291  ! Subroutine intent(in) arguments.
1292  ! --------------------------------
1293  ! * nQuad : Number of quad cells
1294  ! nNodes: Number of nodes in the given grid.
1295  ! Subroutine intent(in), target arguments.
1296  ! ----------------------------------------
1297  ! coor(3,nNodes): Nodal coordinates of the local grid.
1298  ! quadsConn(8,nHexa): Connectivity for quad cells
1299  ! Subroutine intent(out), arguments.
1300  ! ----------------------------------------
1301  ! ADT : The newly completed ADT
1302  !
1303  implicit none
1304  !
1305  ! Subroutine arguments.
1306  !
1307  integer(kind=intType), intent(in) :: nquad
1308  integer(kind=intType), intent(in) :: nnodes
1309 
1310  integer(kind=intType), dimension(:, :), intent(in), &
1311  target :: quadsconn
1312 
1313  real(kind=realtype), dimension(:, :), intent(in), &
1314  target :: coor
1315  type(adttype), intent(out) :: adt
1316  !
1317  ! Local variables.
1318  !
1319  integer :: ierr, ll, nnpe
1320  integer(kind=intType) :: i, j, mm
1321  real(kind=realtype), dimension(3) :: xmin, xmax
1322 
1323  ! We need to set comm...explictly mpi_comm_self
1324  adt%comm = mpi_comm_self
1325  adt%nProcs = 1
1326  adt%myID = 0
1327  ! Set the ADT type, which is a surface ADT.
1328 
1329  adt%adtType = adtsurfaceadt
1330 
1331  ! Copy the number of nodes and volume elements and set the number
1332  ! of surface elements to 0; only a volume grid has been given.
1333 
1334  adt%nNodes = nnodes
1335  adt%nHexa = 0
1336  adt%nTetra = 0
1337  adt%nPyra = 0
1338  adt%nPrisms = 0
1339  adt%nTria = 0
1340  adt%nQuads = nquad
1341 
1342  ! Set the pointers for the coordinates and the
1343  ! volume connectivities.
1344 
1345  adt%coor => coor
1346  adt%quadsConn => quadsconn
1347  nullify (adt%triaConn)
1348 
1349  adt%nBBoxes = nquad
1350 
1351  ! Allocate the memory for the bounding box coordinates, the
1352  ! corresponding element type and the index in the connectivity.
1353 
1354  allocate (adt%xBBox(6, nquad))
1355  allocate (adt%elementType(nquad))
1356  allocate (adt%elementID(nquad))
1357 
1358  ! All hexas
1359  adt%elementType = adtquadrilateral
1360 
1361  ! Loop over the number of elements and store the bounding
1362  ! box info.
1363  nnpe = 4
1364 
1365  do i = 1, nquad
1366 
1367  mm = quadsconn(1, i)
1368  xmin(1) = coor(1, mm); xmax(1) = coor(1, mm)
1369  xmin(2) = coor(2, mm); xmax(2) = coor(2, mm)
1370  xmin(3) = coor(3, mm); xmax(3) = coor(3, mm)
1371 
1372  do j = 2, nnpe
1373  mm = quadsconn(j, i)
1374 
1375  xmin(1) = min(xmin(1), coor(1, mm))
1376  xmin(2) = min(xmin(2), coor(2, mm))
1377  xmin(3) = min(xmin(3), coor(3, mm))
1378 
1379  xmax(1) = max(xmax(1), coor(1, mm))
1380  xmax(2) = max(xmax(2), coor(2, mm))
1381  xmax(3) = max(xmax(3), coor(3, mm))
1382  end do
1383 
1384  adt%xBBox(1, i) = xmin(1)
1385  adt%xBBox(2, i) = xmin(2)
1386  adt%xBBox(3, i) = xmin(3)
1387 
1388  adt%xBBox(4, i) = xmax(1)
1389  adt%xBBox(5, i) = xmax(2)
1390  adt%xBBox(6, i) = xmax(3)
1391 
1392  ! elementID is just sequential since we only have 1 element type
1393  adt%elementID(i) = i
1394 
1395  end do
1396 
1397  ! Build the ADT from the now known boundary boxes.
1398 
1399  call buildadt(adt)
1400 
1401  end subroutine buildserialquad
1402 
1403  subroutine destroyserialquad(ADT)
1404  ! Deallocate the data allocated from the ADT
1405 
1406  implicit none
1407  type(adttype), intent(inout) :: adt
1408 
1409  deallocate (adt%xBBox)
1410  deallocate (adt%elementType)
1411  deallocate (adt%elementID)
1412  deallocate (adt%ADTree)
1413  end subroutine destroyserialquad
1414 end module adtbuild
subroutine setvolumepointers(ll)
Definition: adtBuild.F90:1107
subroutine setsurfacepointers(ll)
Definition: adtBuild.F90:731
subroutine destroyserialquad(ADT)
Definition: adtBuild.F90:1404
subroutine destroyserialhex(ADT)
Definition: adtBuild.F90:1266
subroutine buildadt(ADT)
Definition: adtBuild.F90:19
subroutine buildserialhex(nHexa, nNodes, coor, hexaConn, ADT)
Definition: adtBuild.F90:1141
subroutine buildserialquad(nQuad, nNodes, coor, quadsConn, ADT)
Definition: adtBuild.F90:1278
subroutine buildsurfaceadt(nTria, nQuads, nNodes, coor, triaConn, quadsConn, BBox, useBBox, comm, adtID)
Definition: adtBuild.F90:398
subroutine buildvolumeadt(nTetra, nPyra, nPrisms, nHexa, nNodes, coor, tetraConn, pyraConn, prismsConn, hexaConn, BBox, useBBox, comm, adtID)
Definition: adtBuild.F90:764
subroutine qsortbboxes(arr, nn, ADT, dir)
Definition: adtUtils.F90:326
integer(kind=inttype) nstack
Definition: adtUtils.F90:19
subroutine reallocateadts(adtID, jj)
Definition: adtUtils.F90:676
integer(kind=inttype), dimension(:), pointer stack
Definition: adtUtils.F90:20
subroutine adtterminate(ADT, routineName, errorMessage)
Definition: adtUtils.F90:29
subroutine allocateadts
Definition: adtUtils.F90:144
real(kind=realtype), parameter zero
Definition: constants.F90:71
integer, parameter adtvolumeadt
Definition: constants.F90:246
integer(kind=adtelementtype), parameter adttetrahedron
Definition: constants.F90:251
integer(kind=adtelementtype), parameter adtprism
Definition: constants.F90:253
integer(kind=adtelementtype), parameter adthexahedron
Definition: constants.F90:254
integer(kind=adtelementtype), parameter adttriangle
Definition: constants.F90:249
integer(kind=adtelementtype), parameter adtquadrilateral
Definition: constants.F90:250
integer, parameter adtsurfaceadt
Definition: constants.F90:245
integer(kind=adtelementtype), parameter adtpyramid
Definition: constants.F90:252