44from flow360 .component .simulation .entity_info import GeometryEntityInfo
55from flow360 .component .simulation .framework .param_utils import AssetCache
66from flow360 .component .simulation .meshing_param .face_params import SurfaceRefinement
7- from flow360 .component .simulation .meshing_param .params import MeshingParams
8- from flow360 .component .simulation .primitives import GeometryBodyGroup , GhostSurface
7+ from flow360 .component .simulation .meshing_param .params import (
8+ MeshingDefaults ,
9+ MeshingParams ,
10+ )
11+ from flow360 .component .simulation .primitives import (
12+ GeometryBodyGroup ,
13+ GhostCircularPlane ,
14+ GhostSurface ,
15+ Surface ,
16+ )
917from flow360 .component .simulation .simulation_params import SimulationParams
1018from flow360 .component .simulation .translator .surface_meshing_translator import (
19+ SurfaceRefinement_to_faces ,
1120 get_surface_meshing_json ,
1221)
22+ from flow360 .component .simulation .translator .utils import (
23+ translate_setting_and_apply_to_all_entities ,
24+ )
1325from flow360 .component .simulation .unit_system import SI_unit_system
1426from flow360 .component .simulation .utils import model_attribute_unlock
1527
@@ -28,15 +40,19 @@ def _minimal_geometry_entity_info():
2840 )
2941 ]
3042 ],
31- face_ids = [],
32- face_attribute_names = [],
33- grouped_faces = [[]],
43+ face_ids = ["body00001_face00001" ],
44+ face_attribute_names = ["faceId" ],
45+ grouped_faces = [
46+ [Surface (name = "wall" , private_attribute_sub_components = ["body00001_face00001" ])]
47+ ],
3448 edge_ids = [],
3549 edge_attribute_names = [],
3650 grouped_edges = [[]],
3751 )
3852 with model_attribute_unlock (info , "body_group_tag" ):
3953 info .body_group_tag = "groupByFile"
54+ with model_attribute_unlock (info , "face_group_tag" ):
55+ info .face_group_tag = "faceId"
4056 return info
4157
4258
@@ -74,3 +90,55 @@ def test_surface_refinement_accepts_ghostsurface_and_kept_in_gai_json():
7490 found = True
7591 break
7692 assert found
93+
94+
95+ def test_surface_refinement_uses_boundary_name_for_ghost_circular_plane_with_beta_mesher ():
96+ with SI_unit_system :
97+ ghost = GhostCircularPlane (name = "symmetric" )
98+ params = SimulationParams (
99+ meshing = MeshingParams (
100+ defaults = MeshingDefaults (
101+ surface_max_edge_length = 0.2 * u .m ,
102+ curvature_resolution_angle = 15 * u .deg ,
103+ surface_edge_growth_rate = 1.1 ,
104+ ),
105+ refinements = [
106+ SurfaceRefinement (
107+ entities = [ghost ],
108+ max_edge_length = 0.1 * u .m ,
109+ )
110+ ],
111+ ),
112+ private_attribute_asset_cache = AssetCache (
113+ use_inhouse_mesher = True ,
114+ project_entity_info = _minimal_geometry_entity_info (),
115+ ),
116+ )
117+
118+ translated = get_surface_meshing_json (params , 1.0 * u .m )
119+
120+ assert translated ["faces" ]["symmetric" ] == {
121+ "maxEdgeLength" : pytest .approx (0.1 ),
122+ "curvatureResolutionAngle" : pytest .approx (15.0 ),
123+ }
124+ assert translated ["faces" ]["body00001_face00001" ] == {"maxEdgeLength" : pytest .approx (0.2 )}
125+ assert translated ["boundaries" ]["body00001_face00001" ] == {"boundaryName" : "wall" }
126+
127+
128+ def test_surface_refinement_does_not_fallback_for_empty_sub_component_list ():
129+ with SI_unit_system :
130+ refinement = SurfaceRefinement (
131+ entities = [Surface (name = "wall" , private_attribute_sub_components = [])],
132+ max_edge_length = 0.1 * u .m ,
133+ )
134+
135+ translated = translate_setting_and_apply_to_all_entities (
136+ [refinement ],
137+ SurfaceRefinement ,
138+ translation_func = SurfaceRefinement_to_faces ,
139+ translation_func_global_max_edge_length = 0.2 * u .m ,
140+ translation_func_global_curvature_resolution_angle = 15 * u .deg ,
141+ use_sub_item_as_key = True ,
142+ )
143+
144+ assert translated == {}
0 commit comments