@@ -17,16 +17,196 @@ module m_model
1717
1818 private
1919
20- public :: f_model_read, s_model_write, s_model_free, f_model_is_inside
20+ public :: s_instantiate_STL_models, f_model_read, s_model_write, s_model_free, f_model_is_inside, models, gpu_ntrs, gpu_trs_v, gpu_trs_n
2121
2222 ! Subroutines for STL immersed boundaries
2323 public :: f_check_boundary, f_register_edge, f_check_interpolation_2D, &
2424 f_check_interpolation_3D, f_interpolate_2D, f_interpolate_3D, &
2525 f_interpolated_distance, f_normals, f_distance, f_distance_normals_3D, f_tri_area, s_pack_model_for_gpu, &
2626 f_model_is_inside_flat
2727
28+ !! array of STL models that can be allocated and then used in IB marker and levelset compute
29+ type(t_model_array), allocatable, target :: models(:)
30+ !! GPU- friendly flat arrays for STL model data
31+ integer , allocatable :: gpu_ntrs(:)
32+ real (wp), allocatable, dimension (:, :, :, :) :: gpu_trs_v
33+ real (wp), allocatable, dimension (:, :, :) :: gpu_trs_n
34+ real (wp), allocatable, dimension (:, :, :) :: gpu_boundary_v
35+ real (wp), allocatable, dimension (:, :, :) :: gpu_interpolated_boundary_v
36+
2837contains
2938
39+ subroutine s_instantiate_STL_models ()
40+
41+ ! Variables for IBM+ STL
42+ real (wp) :: normals(1 :3 ) !< Boundary normal buffer
43+ integer :: boundary_vertex_count, boundary_edge_count, total_vertices !< Boundary vertex
44+ real (wp), allocatable, dimension (:, :, :) :: boundary_v !< Boundary vertex buffer
45+ real (wp), allocatable, dimension (:, :) :: interpolated_boundary_v !< Interpolated vertex buffer
46+ real (wp) :: dx_local, dy_local, dz_local !< Levelset distance buffer
47+ logical :: interpolate !< Logical variable to determine whether or not the model should be interpolated
48+
49+ integer :: i, j, k !< Generic loop iterators
50+ integer :: patch_id
51+
52+ type(t_bbox) :: bbox, bbox_old
53+ type(t_model) :: model
54+ type(ic_model_parameters) :: params
55+
56+ real (wp) :: eta
57+ real (wp), dimension (1 :3 ) :: point, model_center
58+ real (wp) :: grid_mm(1 :3 , 1 :2 )
59+
60+ real (wp), dimension (1 :4 , 1 :4 ) :: transform, transform_n
61+
62+ #ifdef MFC_PRE_PROCESS
63+ dx_local = dx; dy_local = dy
64+ if (p /= 0 ) dz_local = dz
65+ #else
66+ dx_local = minval (dx); dy_local = minval (dy)
67+ if (p /= 0 ) dz_local = minval (dz)
68+ #endif
69+
70+ do patch_id = 1 , num_ibs
71+ if (patch_ib(patch_id)%geometry == 5 .or. patch_ib(patch_id)%geometry == 12 ) then
72+ allocate (models(patch_id)%model)
73+ print * , " * Reading model: " // trim (patch_ib(patch_id)%model_filepath)
74+
75+ model = f_model_read(patch_ib(patch_id)%model_filepath)
76+ params%scale (:) = patch_ib(patch_id)%model_scale(:)
77+ params%translate(:) = patch_ib(patch_id)%model_translate(:)
78+ params%rotate(:) = patch_ib(patch_id)%model_rotate(:)
79+ params%spc = patch_ib(patch_id)%model_spc
80+ params%threshold = patch_ib(patch_id)%model_threshold
81+
82+ if (f_approx_equal(dot_product (params%scale, params%scale), 0._wp )) then
83+ params%scale (:) = 1._wp
84+ end if
85+
86+ if (proc_rank == 0 ) then
87+ print * , " * Transforming model."
88+ end if
89+
90+ ! Get the model center before transforming the model
91+ bbox_old = f_create_bbox(model)
92+ model_center(1 :3 ) = (bbox_old%min (1 :3 ) + bbox_old%max (1 :3 ))/ 2._wp
93+
94+ ! Compute the transform matrices for vertices and normals
95+ transform = f_create_transform_matrix(params, model_center)
96+ transform_n = f_create_transform_matrix(params)
97+
98+ call s_transform_model(model, transform, transform_n)
99+
100+ ! Recreate the bounding box after transformation
101+ bbox = f_create_bbox(model)
102+
103+ ! Show the number of vertices in the original STL model
104+ if (proc_rank == 0 ) then
105+ print * , ' * Number of input model vertices:' , 3 * model%ntrs
106+ end if
107+
108+ call f_check_boundary(model, boundary_v, boundary_vertex_count, boundary_edge_count)
109+
110+ ! Check if the model needs interpolation
111+ if (p > 0 ) then
112+ call f_check_interpolation_3D(model, (/ dx_local, dy_local, dz_local/ ), interpolate)
113+ else
114+ call f_check_interpolation_2D(boundary_v, boundary_edge_count, (/ dx_local, dy_local, 0._wp / ), interpolate)
115+ end if
116+
117+ ! Show the number of edges and boundary edges in 2D STL models
118+ if (proc_rank == 0 .and. p == 0 ) then
119+ print * , ' * Number of 2D model boundary edges:' , boundary_edge_count
120+ end if
121+
122+ ! Interpolate the STL model along the edges (2D ) and on triangle facets (3D )
123+ if (interpolate) then
124+ if (proc_rank == 0 ) then
125+ print * , ' * Interpolating STL vertices.'
126+ end if
127+
128+ if (p > 0 ) then
129+ call f_interpolate_3D(model, (/ dx, dy, dz/ ), interpolated_boundary_v, total_vertices)
130+ else
131+ call f_interpolate_2D(boundary_v, boundary_edge_count, (/ dx, dy, dz/ ), interpolated_boundary_v, total_vertices)
132+ end if
133+
134+ if (proc_rank == 0 ) then
135+ print * , ' * Total number of interpolated boundary vertices:' , total_vertices
136+ end if
137+ end if
138+
139+ if (proc_rank == 0 ) then
140+ write (* , " (A, 3(2X, F20.10))" ) " > Model: Min:" , bbox%min (1 :3 )
141+ write (* , " (A, 3(2X, F20.10))" ) " > Cen:" , (bbox%min (1 :3 ) + bbox%max (1 :3 ))/ 2._wp
142+ write (* , " (A, 3(2X, F20.10))" ) " > Max:" , bbox%max (1 :3 )
143+
144+ grid_mm(1 , :) = (/ minval (x_cc(0 :m)) - 0.e5_wp * dx_local, maxval (x_cc(0 :m)) + 0.e5_wp * dx_local/ )
145+ grid_mm(2 , :) = (/ minval (y_cc(0 :n)) - 0.e5_wp * dy_local, maxval (y_cc(0 :n)) + 0.e5_wp * dy_local/ )
146+
147+ if (p > 0 ) then
148+ grid_mm(3 , :) = (/ minval (z_cc(0 :p)) - 0.e5_wp * dz_local, maxval (z_cc(0 :p)) + 0.e5_wp * dz_local/ )
149+ else
150+ grid_mm(3 , :) = (/ 0._wp , 0._wp / )
151+ end if
152+
153+ write (* , " (A, 3(2X, F20.10))" ) " > Domain: Min:" , grid_mm(:, 1 )
154+ write (* , " (A, 3(2X, F20.10))" ) " > Cen:" , (grid_mm(:, 1 ) + grid_mm(:, 2 ))/ 2._wp
155+ write (* , " (A, 3(2X, F20.10))" ) " > Max:" , grid_mm(:, 2 )
156+ end if
157+
158+ models(patch_id)%model = model
159+ models(patch_id)%boundary_v = boundary_v
160+ models(patch_id)%boundary_edge_count = boundary_edge_count
161+ if (interpolate) then
162+ models(patch_id)%interpolate = 1
163+ else
164+ models(patch_id)%interpolate = 0
165+ end if
166+ if (interpolate) then
167+ models(patch_id)%interpolated_boundary_v = interpolated_boundary_v
168+ models(patch_id)%total_vertices = total_vertices
169+ end if
170+
171+ end if
172+ end do
173+
174+ ! Pack and upload flat arrays for GPU (AFTER the loop)
175+ block
176+ integer :: pid, max_ntrs
177+
178+ max_ntrs = 0
179+ do pid = 1 , num_ibs
180+ if (allocated(models(pid)%model)) then
181+ call s_pack_model_for_gpu(models(pid))
182+ max_ntrs = max (max_ntrs, models(pid)%ntrs)
183+ end if
184+ end do
185+
186+ if (max_ntrs > 0 ) then
187+ allocate (gpu_ntrs(1 :num_ibs))
188+ allocate (gpu_trs_v(1 :3 , 1 :3 , 1 :max_ntrs, 1 :num_ibs))
189+ allocate (gpu_trs_n(1 :3 , 1 :max_ntrs, 1 :num_ibs))
190+
191+ gpu_ntrs = 0
192+ gpu_trs_v = 0._wp
193+ gpu_trs_n = 0._wp
194+
195+ do pid = 1 , num_ibs
196+ if (allocated(models(pid)%model)) then
197+ gpu_ntrs(pid) = models(pid)%ntrs
198+ gpu_trs_v(:, :, 1 :models(pid)%ntrs, pid) = models(pid)%trs_v
199+ gpu_trs_n(:, 1 :models(pid)%ntrs, pid) = models(pid)%trs_n
200+ end if
201+ end do
202+
203+ $:GPU_ENTER_DATA(copyin= ' [gpu_ntrs, gpu_trs_v, gpu_trs_n]' )
204+
205+ end if
206+ end block
207+
208+ end subroutine s_instantiate_STL_models
209+
30210 !> This procedure reads a binary STL file.
31211 !! @param filepath Path to the STL file.
32212 !! @param model The binary of the STL file.
0 commit comments