Neko 1.99.1
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
aabb.f90
Go to the documentation of this file.
1! Copyright (c) 2024, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
33! ============================================================================ !
34! Original C++ Implementation from:
35! https://github.com/JamesRandall/SimpleVoxelEngine/blob/master/voxelEngine/include/AABB.h
36!
37! Translated to Fortran by:
38! @author Tim Felle Olsen
39! @date 9 Feb 2024
40!
41! C++ Code License:
42! The MIT License (MIT)
43!
44! Copyright (c) 2017 James Randall
45!
46! Permission is hereby granted, free of charge, to any person obtaining a copy of
47! this software and associated documentation files (the "Software"), to deal in
48! the Software without restriction, including without limitation the rights to
49! use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
50! the Software, and to permit persons to whom the Software is furnished to do so,
51! subject to the following conditions:
52!
53! The above copyright notice and this permission notice shall be included in all
54! copies or substantial portions of the Software.
55!
56! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
57! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
58! FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
59! COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
60! IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
61! CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
62! ============================================================================ !
63
71module aabb
72 use num_types, only: dp
73 use element, only: element_t
74 use point, only: point_t
75 use tri, only: tri_t
76 use quad, only: quad_t
77 use tet, only: tet_t
78 use hex, only: hex_t
79 use mesh, only: mesh_t
80 use tri_mesh, only: tri_mesh_t
81 use tet_mesh, only: tet_mesh_t
82 use utils, only: neko_error
83
84 implicit none
85 private
87
88 ! ========================================================================== !
89 ! Public interface for free functions
90 ! ========================================================================== !
91
93 interface merge
94 module procedure merge_aabb
95 end interface merge
96
98 interface intersection
99 module procedure intersection_aabb
100 end interface intersection
101
107 type :: aabb_t
108 private
109
110 logical :: initialized = .false.
111 real(kind=dp) :: box_min(3) = huge(0.0_dp)
112 real(kind=dp) :: box_max(3) = -huge(0.0_dp)
113 real(kind=dp) :: center(3) = 0.0_dp
114 real(kind=dp) :: diameter = huge(0.0_dp)
115 real(kind=dp) :: surface_area = 0.0_dp
116
117 contains
118
119 ! Initializers
120 procedure, pass(this), public :: init => aabb_init
121
122 ! Getters
123 procedure, pass(this), public :: get_min => aabb_get_min
124 procedure, pass(this), public :: get_max => aabb_get_max
125 procedure, pass(this), public :: get_width => aabb_get_width
126 procedure, pass(this), public :: get_height => aabb_get_height
127 procedure, pass(this), public :: get_depth => aabb_get_depth
128 procedure, pass(this), public :: get_diameter => aabb_get_diameter
129 procedure, pass(this), public :: get_surface_area => aabb_get_surface_area
130 procedure, pass(this), public :: get_center => aabb_get_center
131 procedure, pass(this), public :: get_diagonal => aabb_get_diagonal
132
133 procedure, pass(this), public :: add_padding
134
135 ! Comparison operators
136 generic :: operator(.lt.) => less
137 generic :: operator(.gt.) => greater
138
140 procedure, pass(this), public :: overlaps => aabb_overlaps
142 procedure, pass(this), public :: contains => aabb_contains_other
144 procedure, pass(this), public :: contains_point => aabb_contains_point
145
146 ! Private comparison operators
147 procedure, pass(this) :: less => aabb_less
148 procedure, pass(this) :: greater => aabb_greater
149
150 ! Private operations
151 procedure, pass(this), private :: calculate_surface_area
152
153 end type aabb_t
154
155contains
156
157 ! ========================================================================== !
158 ! Constructors
159 ! ========================================================================== !
160
180 function get_aabb(object, padding) result(box)
181 use utils, only: neko_error
182 implicit none
183
184 class(*), intent(in) :: object
185 real(kind=dp), intent(in), optional :: padding
186 type(aabb_t) :: box
187
188 select type(object)
189
190 type is (aabb_t)
191 call box%init(object%get_min(), object%get_max())
192 type is (point_t)
193 box = get_aabb_point(object)
194 type is (tri_t)
195 box = get_aabb_element(object)
196 type is (hex_t)
197 box = get_aabb_element(object)
198 type is (tet_t)
199 box = get_aabb_element(object)
200 type is (quad_t)
201 box = get_aabb_element(object)
202 class is (element_t)
203 box = get_aabb_element(object)
204
205
206 type is (mesh_t)
207 box = get_aabb_mesh(object)
208 type is (tri_mesh_t)
209 box = get_aabb_tri_mesh(object)
210 type is (tet_mesh_t)
211 box = get_aabb_tet_mesh(object)
212
213 class default
214 call neko_error("get_aabb: Unsupported object type")
215 end select
216
217 if (present(padding)) then
218 call box%add_padding(padding)
219 end if
220
221 end function get_aabb
222
228 subroutine add_padding(this, padding)
229 class(aabb_t), intent(inout) :: this
230 real(kind=dp), intent(in) :: padding
231 real(kind=dp) :: box_min(3), box_max(3)
232
233 box_min = this%box_min - padding * (this%diameter)
234 box_max = this%box_max + padding * (this%diameter)
235
236 call this%init(box_min, box_max)
237 end subroutine add_padding
238
239
246 function get_aabb_point(object) result(box)
247 type(point_t), intent(in) :: object
248 type(aabb_t) :: box
249
250 integer :: i
251 real(kind=dp) :: box_min(3), box_max(3)
252
253 box_min = huge(0.0_dp)
254 box_max = -huge(0.0_dp)
255 box_min = min(box_min, object%x)
256 box_max = max(box_max, object%x)
257 call box%init(box_min, box_max)
258 end function get_aabb_point
259
269 function get_aabb_element(object) result(box)
270 class(element_t), intent(in) :: object
271 type(aabb_t) :: box
272
273 integer :: i
274 type(point_t), pointer :: pi
275 real(kind=dp) :: box_min(3), box_max(3)
276
277 box_min = huge(0.0_dp); box_max = -huge(0.0_dp)
278
279 do i = 1, object%n_points()
280 pi => object%p(i)
281 box_min = min(box_min, pi%x)
282 box_max = max(box_max, pi%x)
283 end do
284
285 call box%init(box_min, box_max)
286 end function get_aabb_element
287
296 function get_aabb_mesh(object) result(box)
297 type(mesh_t), intent(in) :: object
298 type(aabb_t) :: box
299
300 integer :: i
301 type(aabb_t) :: temp_box
302
303 do i = 1, object%nelv
304 temp_box = get_aabb(object%elements(i))
305 box = merge(box, temp_box)
306 end do
307
308 end function get_aabb_mesh
309
318 function get_aabb_tri_mesh(object) result(box)
319 type(tri_mesh_t), intent(in) :: object
320 type(aabb_t) :: box
321
322 integer :: i
323 type(aabb_t) :: temp_box
324
325 do i = 1, object%nelv
326 temp_box = get_aabb(object%el(i))
327 box = merge(box, temp_box)
328 end do
329
330 end function get_aabb_tri_mesh
331
340 function get_aabb_tet_mesh(object) result(box)
341 type(tet_mesh_t), intent(in) :: object
342 type(aabb_t) :: box
343
344 integer :: i
345 type(aabb_t) :: temp_box
346
347 do i = 1, object%nelv
348 temp_box = get_aabb(object%el(i))
349 box = merge(box, temp_box)
350 end do
351
352 end function get_aabb_tet_mesh
353
354
355 ! ========================================================================== !
356 ! Initializers
357 ! ========================================================================== !
358
362 subroutine aabb_init(this, lower_left_front, upper_right_back)
363 class(aabb_t), intent(inout) :: this
364 real(kind=dp), dimension(3), intent(in) :: lower_left_front
365 real(kind=dp), dimension(3), intent(in) :: upper_right_back
366
367 this%initialized = .true.
368 this%box_min = lower_left_front
369 this%box_max = upper_right_back
370 this%center = (this%box_min + this%box_max) / 2.0_dp
371 this%diameter = norm2(this%box_max - this%box_min)
372
373 this%surface_area = this%calculate_surface_area()
374
375 end subroutine aabb_init
376
377 ! ========================================================================== !
378 ! Getters
379 ! ========================================================================== !
380
382 pure function aabb_get_min(this) result(min)
383 class(aabb_t), intent(in) :: this
384 real(kind=dp), dimension(3) :: min
385
386 min = this%box_min
387 end function aabb_get_min
388
390 pure function aabb_get_max(this) result(max)
391 class(aabb_t), intent(in) :: this
392 real(kind=dp), dimension(3) :: max
393
394 max = this%box_max
395 end function aabb_get_max
396
398 pure function aabb_get_width(this) result(width)
399 class(aabb_t), intent(in) :: this
400 real(kind=dp) :: width
401
402 width = this%box_max(1) - this%box_min(1)
403 end function aabb_get_width
404
406 pure function aabb_get_depth(this) result(depth)
407 class(aabb_t), intent(in) :: this
408 real(kind=dp) :: depth
409
410 depth = this%box_max(2) - this%box_min(2)
411 end function aabb_get_depth
412
414 pure function aabb_get_height(this) result(height)
415 class(aabb_t), intent(in) :: this
416 real(kind=dp) :: height
417
418 height = this%box_max(3) - this%box_min(3)
419 end function aabb_get_height
420
422 pure function aabb_get_diameter(this) result(diameter)
423 class(aabb_t), intent(in) :: this
424 real(kind=dp) :: diameter
425
426 diameter = this%diameter
427 end function aabb_get_diameter
428
430 pure function aabb_get_surface_area(this) result(surface_area)
431 class(aabb_t), intent(in) :: this
432 real(kind=dp) :: surface_area
433
434 surface_area = this%surface_area
435 end function aabb_get_surface_area
436
438 pure function aabb_get_center(this) result(center)
439 class(aabb_t), intent(in) :: this
440 real(kind=dp), dimension(3) :: center
441
442 center = this%center
443 end function aabb_get_center
444
446 pure function aabb_get_diagonal(this) result(diagonal)
447 class(aabb_t), intent(in) :: this
448 real(kind=dp), dimension(3) :: diagonal
449
450 diagonal = this%box_max - this%box_min
451 end function aabb_get_diagonal
452
453 ! ========================================================================== !
454 ! Operations
455 ! ========================================================================== !
456
458 function aabb_overlaps(this, other) result(is_overlapping)
459 class(aabb_t), intent(in) :: this
460 class(aabb_t), intent(in) :: other
461 logical :: is_overlapping
462
463 if (.not. this%initialized .or. .not. other%initialized) then
464 ! call neko_error("aabb_overlaps: One or both aabbs are not initialized")
465 is_overlapping = .false.
466 else
467 is_overlapping = all(this%box_min .le. other%box_max) .and. &
468 all(this%box_max .ge. other%box_min)
469 end if
470
471 end function aabb_overlaps
472
474 function aabb_contains_other(this, other) result(is_contained)
475 class(aabb_t), intent(in) :: this
476 class(aabb_t), intent(in) :: other
477 logical :: is_contained
478
479 ! if (.not. this%initialized .or. .not. other%initialized) then
480 ! call neko_error("aabb_contains: One or both aabbs are not initialized")
481 ! end if
482
483 is_contained = all(this%box_min .le. other%box_min) .and. &
484 all(this%box_max .ge. other%box_max)
485
486 end function aabb_contains_other
487
489 function aabb_contains_point(this, p) result(is_contained)
490 class(aabb_t), intent(in) :: this
491 real(kind=dp), dimension(3), intent(in) :: p
492 logical :: is_contained
493
494 ! if (.not. this%initialized) then
495 ! call neko_error("aabb_contains_point: One or both aabbs are not initialized")
496 ! end if
497
498 is_contained = all(p .ge. this%box_min) .and. all(p .le. this%box_max)
499 end function aabb_contains_point
500
501 ! ========================================================================== !
502 ! Binary operations
503 ! ========================================================================== !
504
506 function merge_aabb(box1, box2) result(merged)
507 class(aabb_t), intent(in) :: box1
508 class(aabb_t), intent(in) :: box2
509 type(aabb_t) :: merged
510
511 real(kind=dp), dimension(3) :: box_min, box_max
512
513 box_min = min(box1%box_min, box2%box_min)
514 box_max = max(box1%box_max, box2%box_max)
515
516 call merged%init(box_min, box_max)
517 end function merge_aabb
518
520 function intersection_aabb(box1, box2) result(intersected)
521 class(aabb_t), intent(in) :: box1
522 class(aabb_t), intent(in) :: box2
523 type(aabb_t) :: intersected
524
525 real(kind=dp), dimension(3) :: box_min, box_max
526
527 box_min = max(box1%box_min, box2%box_min)
528 box_max = min(box1%box_max, box2%box_max)
529
530 call intersected%init(box_min, box_max)
531 end function intersection_aabb
532
533 ! ========================================================================== !
534 ! Private operations
535 ! ========================================================================== !
536
538 pure function calculate_surface_area(this) result(surface_area)
539 class(aabb_t), intent(in) :: this
540 real(kind=dp) :: surface_area
541
542 surface_area = 2.0 * ( &
543 this%get_width() * this%get_height() &
544 + this%get_width() * this%get_depth() &
545 + this%get_height() * this%get_depth())
546 end function calculate_surface_area
547
548 ! ========================================================================== !
549 ! Comparison operators
550 ! ========================================================================== !
551
553 pure function aabb_less(this, other)
554 class(aabb_t), intent(in) :: this
555 class(aabb_t), intent(in) :: other
556 logical :: aabb_less
557 logical :: equal
558
559 if (.not. this%initialized .or. .not. other%initialized) then
560 aabb_less = .false.
561 return
562 end if
563
564 aabb_less = this%box_min(1) .lt. other%box_min(1)
565 equal = this%box_min(1) .le. other%box_min(1)
566
567 if (.not. aabb_less .and. equal) then
568 aabb_less = this%box_min(2) .lt. other%box_min(2)
569 equal = this%box_min(2) .le. other%box_min(2)
570 end if
571 if (.not. aabb_less .and. equal) then
572 aabb_less = this%box_min(3) .lt. other%box_min(3)
573 equal = this%box_min(3) .le. other%box_min(3)
574 end if
575 if (.not. aabb_less .and. equal) then
576 aabb_less = this%box_max(1) .lt. other%box_max(1)
577 equal = this%box_max(1) .le. other%box_max(1)
578 end if
579 if (.not. aabb_less .and. equal) then
580 aabb_less = this%box_max(2) .lt. other%box_max(2)
581 equal = this%box_max(2) .le. other%box_max(2)
582 end if
583 if (.not. aabb_less .and. equal) then
584 aabb_less = this%box_max(3) .lt. other%box_max(3)
585 end if
586
587 end function aabb_less
588
590 pure function aabb_greater(this, other)
591 class(aabb_t), intent(in) :: this
592 class(aabb_t), intent(in) :: other
593 logical :: aabb_greater
594 logical :: equal
595
596 if (.not. this%initialized .or. .not. other%initialized) then
597 aabb_greater = .false.
598 return
599 end if
600
601 aabb_greater = this%box_min(1) .gt. other%box_min(1)
602 equal = this%box_min(1) .ge. other%box_min(1)
603
604 if (.not. aabb_greater .and. equal) then
605 aabb_greater = this%box_min(2) .gt. other%box_min(2)
606 equal = this%box_min(2) .ge. other%box_min(2)
607 end if
608 if (.not. aabb_greater .and. equal) then
609 aabb_greater = this%box_min(3) .gt. other%box_min(3)
610 equal = this%box_min(3) .ge. other%box_min(3)
611 end if
612 if (.not. aabb_greater .and. equal) then
613 aabb_greater = this%box_max(1) .gt. other%box_max(1)
614 equal = this%box_max(1) .ge. other%box_max(1)
615 end if
616 if (.not. aabb_greater .and. equal) then
617 aabb_greater = this%box_max(2) .gt. other%box_max(2)
618 equal = this%box_max(2) .ge. other%box_max(2)
619 end if
620 if (.not. aabb_greater .and. equal) then
621 aabb_greater = this%box_max(3) .gt. other%box_max(3)
622 end if
623
624 end function aabb_greater
625
626end module aabb
Intersect two aabbs.
Definition aabb.f90:98
Merge two aabbs.
Definition aabb.f90:93
Axis Aligned Bounding Box (aabb) implementation in Fortran.
Definition aabb.f90:71
pure real(kind=dp) function, dimension(3) aabb_get_max(this)
Get the maximum point of the aabb.
Definition aabb.f90:391
pure real(kind=dp) function aabb_get_surface_area(this)
Get the surface area of the aabb.
Definition aabb.f90:431
pure real(kind=dp) function aabb_get_diameter(this)
Get the diameter length of the aabb.
Definition aabb.f90:423
subroutine add_padding(this, padding)
Add padding to the aabb.
Definition aabb.f90:229
logical function aabb_contains_point(this, p)
Check if this aabb contains a point.
Definition aabb.f90:490
subroutine aabb_init(this, lower_left_front, upper_right_back)
Initialize the aabb.
Definition aabb.f90:363
type(aabb_t) function get_aabb_point(object)
Get the aabb of a point.
Definition aabb.f90:247
type(aabb_t) function get_aabb_tri_mesh(object)
Get the aabb of a triangular mesh.
Definition aabb.f90:319
logical function aabb_overlaps(this, other)
Check if two aabbs are overlapping.
Definition aabb.f90:459
type(aabb_t) function get_aabb_mesh(object)
Get the aabb of a mesh.
Definition aabb.f90:297
type(aabb_t) function intersection_aabb(box1, box2)
Get the intersection of two aabbs.
Definition aabb.f90:521
pure real(kind=dp) function aabb_get_height(this)
Get the height of the aabb. Also known as the z-axis length.
Definition aabb.f90:415
pure logical function aabb_greater(this, other)
Greater than comparison operator.
Definition aabb.f90:591
type(aabb_t) function, public get_aabb(object, padding)
Construct the aabb of a predefined object.
Definition aabb.f90:181
logical function aabb_contains_other(this, other)
Check if this aabb contains another aabb.
Definition aabb.f90:475
pure real(kind=dp) function calculate_surface_area(this)
Calculate the surface area of the aabb.
Definition aabb.f90:539
pure logical function aabb_less(this, other)
Less than comparison operator.
Definition aabb.f90:554
type(aabb_t) function get_aabb_element(object)
Get the aabb of an arbitrary element.
Definition aabb.f90:270
type(aabb_t) function get_aabb_tet_mesh(object)
Get the aabb of a tetrahedral mesh.
Definition aabb.f90:341
pure real(kind=dp) function, dimension(3) aabb_get_center(this)
Get the center of the aabb.
Definition aabb.f90:439
pure real(kind=dp) function aabb_get_width(this)
Get the width of the aabb. Also known as the x-axis length.
Definition aabb.f90:399
pure real(kind=dp) function, dimension(3) aabb_get_diagonal(this)
Get the diagonal of the aabb.
Definition aabb.f90:447
type(aabb_t) function merge_aabb(box1, box2)
Merge two aabbs.
Definition aabb.f90:507
pure real(kind=dp) function aabb_get_depth(this)
Get the depth of the aabb. Also known as the y-axis length.
Definition aabb.f90:407
pure real(kind=dp) function, dimension(3) aabb_get_min(this)
Get the minimum point of the aabb.
Definition aabb.f90:383
Defines a hexahedron element.
Definition hex.f90:34
Defines a mesh.
Definition mesh.f90:34
integer, parameter, public dp
Definition num_types.f90:9
Implements a point.
Definition point.f90:35
Defines a quadrilateral element.
Definition quad.f90:34
Defines a tetrahedral mesh.
Definition tet_mesh.f90:35
Defines a tetrahedral element.
Definition tet.f90:34
Defines a triangular surface mesh.
Definition tri_mesh.f90:35
Defines a triangular element.
Definition tri.f90:34
Utilities.
Definition utils.f90:35
Axis Aligned Bounding Box (aabb) data structure.
Definition aabb.f90:107
Base type for an element.
Definition element.f90:44
Hexahedron element.
Definition hex.f90:63
A point in with coordinates .
Definition point.f90:43
Quadrilateral element.
Definition quad.f90:58
Tetrahedral element.
Definition tet.f90:63
Triangular element.
Definition tri.f90:61
#define max(a, b)
Definition tensor.cu:40