@@ -20,6 +20,20 @@ module m_compute_levelset
2020
2121contains
2222
23+ !> 3x3 matrix- vector multiply; replaces the matmul () intrinsic which triggers an ifx 2025.1 .1 SPIR- V ICE (#5633 ) when inlined
24+ !! into a target teams loop kernel via declare target.
25+ pure function f_mv3 (M , v ) result(w)
26+
27+ $:GPU_ROUTINE(parallelism= ' [seq]' )
28+
29+ real (wp), intent (in ) :: M(3 , 3 ), v(3 )
30+ real (wp) :: w(3 )
31+ w(1 ) = M(1 , 1 )* v(1 ) + M(1 , 2 )* v(2 ) + M(1 , 3 )* v(3 )
32+ w(2 ) = M(2 , 1 )* v(1 ) + M(2 , 2 )* v(2 ) + M(2 , 3 )* v(3 )
33+ w(3 ) = M(3 , 1 )* v(1 ) + M(3 , 2 )* v(2 ) + M(3 , 3 )* v(3 )
34+
35+ end function f_mv3
36+
2337 !> Dispatch level- set distance and normal computations for all ghost points based on patch geometry type
2438 impure subroutine s_apply_levelset (gps , num_gps )
2539
@@ -159,7 +173,7 @@ contains
159173 offset(:) = patch_ib(ib_patch_id)%centroid_offset(:)
160174
161175 xy_local = [x_cc(i) - center(1 ), y_cc(j) - center(2 ), 0._wp ] ! get coordinate frame centered on IB
162- xy_local = matmul (inverse_rotation, xy_local) ! rotate the frame into the IB' s coordinate
176+ xy_local = f_mv3 (inverse_rotation, xy_local) ! rotate the frame into the IB' s coordinate
163177 xy_local = xy_local - offset ! airfoils are a patch that require a centroid offset
164178
165179 if (xy_local(2) >= 0._wp) then
@@ -209,7 +223,7 @@ contains
209223 if (f_approx_equal(dist, 0._wp)) then
210224 gp%levelset_norm = 0._wp
211225 else
212- gp%levelset_norm = matmul (rotation, dist_vec(:))/dist ! convert the normal vector back to global grid coordinates
226+ gp%levelset_norm = f_mv3 (rotation, dist_vec(:))/dist ! convert the normal vector back to global grid coordinates
213227 end if
214228
215229 end subroutine s_airfoil_levelset
@@ -244,7 +258,7 @@ contains
244258 z_min = -lz/2
245259
246260 xyz_local = [x_cc(i), y_cc(j), z_cc(l)] - center
247- xyz_local = matmul (inverse_rotation, xyz_local) ! rotate the frame into the IB' s coordinates
261+ xyz_local = f_mv3 (inverse_rotation, xyz_local) ! rotate the frame into the IB' s coordinates
248262 xyz_local = xyz_local - offset ! airfoils are a patch that require a centroid offset
249263
250264 if (xyz_local(2 ) >= 0._wp ) then
@@ -299,13 +313,13 @@ contains
299313 else
300314 normal(3 ) = 1._wp
301315 end if
302- gp%levelset_norm = matmul (rotation, normal)
316+ gp%levelset_norm = f_mv3 (rotation, normal)
303317 else
304318 gp%levelset = dist_surf
305319 if (f_approx_equal(dist_surf, 0._wp )) then
306320 gp%levelset_norm = 0._wp
307321 else
308- gp%levelset_norm = matmul (rotation, dist_vec(:)/ dist_surf)
322+ gp%levelset_norm = f_mv3 (rotation, dist_vec(:)/ dist_surf)
309323 end if
310324 end if
311325
@@ -345,7 +359,7 @@ contains
345359
346360 ! convert grid to local coordinates
347361 xy_local = [x_cc(i) - center(1 ), y_cc(j) - center(2 ), 0._wp ]
348- xy_local = matmul (inverse_rotation, xy_local)
362+ xy_local = f_mv3 (inverse_rotation, xy_local)
349363
350364 side_dists(1 ) = bottom_left(1 ) - xy_local(1 )
351365 side_dists(2 ) = top_right(1 ) - xy_local(1 )
@@ -372,7 +386,7 @@ contains
372386 dist_vec(2 ) = side_dists(idx)/ abs (side_dists(idx))
373387 end if
374388 ! convert the normal vector back into the global coordinate system
375- gp%levelset_norm = matmul (rotation, dist_vec)
389+ gp%levelset_norm = f_mv3 (rotation, dist_vec)
376390 else
377391 gp%levelset_norm = 0._wp
378392 end if
@@ -408,13 +422,13 @@ contains
408422 ellipse_coeffs(2 ) = 0.5_wp * length_y
409423
410424 xy_local = [x_cc(i) - center(1 ), y_cc(j) - center(2 ), 0._wp ]
411- xy_local = matmul (inverse_rotation, xy_local)
425+ xy_local = f_mv3 (inverse_rotation, xy_local)
412426
413427 normal_vector = xy_local
414428 ! get the normal direction via the coordinate transformation method
415429 normal_vector(2 ) = normal_vector(2 )* (ellipse_coeffs(1 )/ ellipse_coeffs(2 ))** 2._wp
416430 normal_vector = normal_vector/ sqrt (dot_product (normal_vector, normal_vector)) ! normalize the vector
417- gp%levelset_norm = matmul (rotation, normal_vector) ! save after rotating the vector to the global frame
431+ gp%levelset_norm = f_mv3 (rotation, normal_vector) ! save after rotating the vector to the global frame
418432
419433 ! use the normal vector to set up the quadratic equation for the levelset, using A, B, and C in indices 1 , 2 , and 3
420434 quadratic_coeffs(1 ) = (normal_vector(1 )/ ellipse_coeffs(1 ))** 2 + (normal_vector(2 )/ ellipse_coeffs(2 ))** 2
@@ -467,7 +481,7 @@ contains
467481 Back = - length_z/ 2
468482
469483 xyz_local = [x_cc(i), y_cc(j), z_cc(k)] - center ! get coordinate frame centered on IB
470- xyz_local = matmul (inverse_rotation, xyz_local) ! rotate the frame into the IB' s coordinate
484+ xyz_local = f_mv3 (inverse_rotation, xyz_local) ! rotate the frame into the IB' s coordinate
471485
472486 dist_left = Left - xyz_local(1)
473487 dist_right = xyz_local(1) - Right
@@ -511,7 +525,7 @@ contains
511525 end if
512526 end if
513527
514- gp%levelset_norm = matmul (rotation, dist_vec)
528+ gp%levelset_norm = f_mv3 (rotation, dist_vec)
515529
516530 end subroutine s_cuboid_levelset
517531
@@ -600,7 +614,7 @@ contains
600614 end if
601615
602616 xyz_local = [x_cc(i), y_cc(j), z_cc(k)] - center ! get coordinate frame centered on IB
603- xyz_local = matmul (inverse_rotation, xyz_local) ! rotate the frame into the IB' s coordinates
617+ xyz_local = f_mv3 (inverse_rotation, xyz_local) ! rotate the frame into the IB' s coordinates
604618
605619 ! get distance to flat edge of cylinder
606620 side_pos = dot_product (xyz_local, dist_sides_vec)
@@ -612,15 +626,15 @@ contains
612626 ! if the closest edge is flat
613627 gp%levelset = - dist_side
614628 if (f_approx_equal(dist_side, abs (side_pos - boundary(1 )))) then
615- gp%levelset_norm = matmul (rotation, - dist_sides_vec)
629+ gp%levelset_norm = f_mv3 (rotation, - dist_sides_vec)
616630 else
617- gp%levelset_norm = matmul (rotation, dist_sides_vec)
631+ gp%levelset_norm = f_mv3 (rotation, dist_sides_vec)
618632 end if
619633 else
620634 gp%levelset = dist_surface
621635 xyz_local = xyz_local* dist_surface_vec
622636 xyz_local = xyz_local/ max (norm2(xyz_local), sgm_eps)
623- gp%levelset_norm = matmul (rotation, xyz_local)
637+ gp%levelset_norm = f_mv3 (rotation, xyz_local)
624638 end if
625639
626640 end subroutine s_cylinder_levelset
@@ -663,7 +677,7 @@ contains
663677 if (p > 0 ) then
664678 xyz_local(3 ) = z_cc(k) - center(3 )
665679 end if
666- xyz_local = matmul (inverse_rotation, xyz_local)
680+ xyz_local = f_mv3 (inverse_rotation, xyz_local)
667681
668682 ! 3D models
669683 if (p > 0 ) then
@@ -675,12 +689,12 @@ contains
675689 gp%levelset = - abs (gp%levelset)
676690
677691 ! Assign the levelset_norm
678- gp%levelset_norm = matmul (rotation, normals(1 :3 ))
692+ gp%levelset_norm = f_mv3 (rotation, normals(1 :3 ))
679693 else
680694 ! 2D models
681695 call s_distance_normals_2D(patch_id, boundary_edge_count, xyz_local, normals, distance)
682696 gp%levelset = - abs (distance)
683- gp%levelset_norm = matmul (rotation, normals(1 :3 ))
697+ gp%levelset_norm = f_mv3 (rotation, normals(1 :3 ))
684698 end if
685699
686700 end subroutine s_model_levelset
0 commit comments