@@ -479,6 +479,23 @@ contains
479479 is_buffered = .true.
480480 end subroutine s_skip_ignored_lines
481481
482+ !> This function is used to replace the fortran random number
483+ !! generator because the native generator is not compatible being called
484+ !! from GPU routines/ functions
485+ function f_model_random_number (seed ) result(rval)
486+
487+ ! $:GPU_ROUTINE(parallelism= ' [seq]' )
488+
489+ integer , intent (inout ) :: seed
490+ real (wp) :: rval
491+
492+ seed = ieor (seed, ishft(seed, 13 ))
493+ seed = ieor (seed, ishft(seed, - 17 ))
494+ seed = ieor (seed, ishft(seed, 5 ))
495+
496+ rval = abs (real (seed, wp)) / real (huge (seed), wp)
497+ end function f_model_random_number
498+
482499 !> This procedure, recursively, finds whether a point is inside an octree.
483500 !! @param model Model to search in .
484501 !! @param point Point to test.
@@ -493,44 +510,48 @@ contains
493510 real (wp), dimension (1 :3 ), intent (in ) :: point
494511 real (wp), dimension (1 :3 ), intent (in ) :: spacing
495512 integer , intent (in ) :: spc
513+ real (wp) :: phi, theta
514+ integer :: rand_seed
496515
497516 real (wp) :: fraction
498517
499518 type(t_ray) :: ray
500- integer :: i, j, nInOrOut, nHits
519+ integer :: i, j, k, nInOrOut, nHits
501520
502521 real (wp), dimension (1 :spc, 1 :3 ) :: ray_origins, ray_dirs
503522
504- ! TODO :: The random number generation prohibits GPU compute due to the subroutine not being able to be called in kernels
505- ! This should be swapped out with something that allows GPU compute. I recommend the fibonacci sphere:
506- ! do i = 1 , spc
507- ! phi = acos (1.0 - 2.0 * (i-1.0 )/ (spc-1.0 ))
508- ! theta = pi * (1.0 + sqrt (5.0 )) * (i-1.0 )
509- ! ray_dirs(i,:) = [cos (theta)* sin (phi), sin (theta)* sin (phi), cos (phi)]
510- ! ray_origins(i,:) = point
511- ! end do
523+ rand_seed = int (point(1 ) * 73856093_wp ) + &
524+ int (point(2 ) * 19349663_wp ) + &
525+ int (point(3 ) * 83492791_wp )
526+ if (rand_seed == 0 ) rand_seed = 1
512527
528+ ! generate our random collection or rays
513529 do i = 1 , spc
514- call random_number (ray_origins(i, :))
515- ray_origins(i, :) = point + (ray_origins(i, :) - 0.5_wp )* spacing (:)
516-
517- call random_number (ray_dirs(i, :))
518- ray_dirs(i, :) = ray_dirs(i, :) - 0.5_wp
530+ do k = 1 , 3
531+ ! random jitter in the origin helps us estimate volume fraction instead of only at the cell center
532+ ray_origins(i, k) = point(k) + (f_model_random_number(rand_seed) - 0.5_wp ) * spacing (k)
533+ ! cast sample rays in all directions
534+ ray_dirs(i, k) = point(k) + f_model_random_number(rand_seed) - 0.5_wp
535+ end do
519536 ray_dirs(i, :) = ray_dirs(i, :)/ sqrt (sum (ray_dirs(i, :)* ray_dirs(i, :)))
520537 end do
521538
539+ ! ray trace
522540 nInOrOut = 0
523541 do i = 1 , spc
524542 ray%o = ray_origins(i, :)
525543 ray%d = ray_dirs(i, :)
526544
527545 nHits = 0
528546 do j = 1 , model%ntrs
547+ ! count the number of triangles this ray intersects
529548 if (f_intersects_triangle(ray, model%trs(j))) then
530549 nHits = nHits + 1
531550 end if
532551 end do
533552
553+ ! if thje ray hits an odd number of triangles on its way out , then
554+ ! it must be on the inside of the model
534555 nInOrOut = nInOrOut + mod (nHits, 2 )
535556 end do
536557
0 commit comments