diff --git a/flow360/component/simulation/meshing_param/snappy/snappy_mesh_refinements.py b/flow360/component/simulation/meshing_param/snappy/snappy_mesh_refinements.py index 0beed13d3..34645afdd 100644 --- a/flow360/component/simulation/meshing_param/snappy/snappy_mesh_refinements.py +++ b/flow360/component/simulation/meshing_param/snappy/snappy_mesh_refinements.py @@ -12,7 +12,6 @@ from flow360.component.simulation.meshing_param.volume_params import UniformRefinement from flow360.component.simulation.primitives import SnappyBody, Surface from flow360.component.simulation.unit_system import AngleType, LengthType -from flow360.log import log class SnappyEntityRefinement(Flow360BaseModel, metaclass=ABCMeta): @@ -36,11 +35,10 @@ def _check_spacing_order(self) -> Self: def _check_proximity_spacing(self) -> Self: if self.min_spacing and self.proximity_spacing: if self.proximity_spacing > self.min_spacing: - log.warning( - f"Proximity spacing ({self.proximity_spacing}) was set higher than the minimal spacing" - + f"({self.min_spacing}), setting proximity spacing to minimal spacing." + raise ValueError( + f"Proximity spacing ({self.proximity_spacing}) was set higher than the minimal spacing " + + f"({self.min_spacing})." ) - self.proximity_spacing = self.min_spacing return self diff --git a/flow360/component/simulation/meshing_param/snappy/snappy_params.py b/flow360/component/simulation/meshing_param/snappy/snappy_params.py index b5f1097ca..44328b81d 100644 --- a/flow360/component/simulation/meshing_param/snappy/snappy_params.py +++ b/flow360/component/simulation/meshing_param/snappy/snappy_params.py @@ -56,8 +56,16 @@ def _check_body_refinements_w_defaults(self): return self for refinement in self.refinements: if isinstance(refinement, BodyRefinement): + if refinement.min_spacing is None and refinement.proximity_spacing: + if refinement.proximity_spacing > self.defaults.min_spacing: + raise ValueError( + f"Proximity spacing for a BodyRefinement ({refinement.proximity_spacing}) was set higher " + + f"than the minimal spacing ({self.defaults.min_spacing})." + ) + if refinement.min_spacing is None and refinement.max_spacing is None: continue + if refinement.min_spacing is None and self.defaults.min_spacing.to( "m" ) > refinement.max_spacing.to("m"): diff --git a/tests/simulation/params/meshing_validation/test_refinements_validation.py b/tests/simulation/params/meshing_validation/test_refinements_validation.py index 13fcfda77..fe5df3001 100644 --- a/tests/simulation/params/meshing_validation/test_refinements_validation.py +++ b/tests/simulation/params/meshing_validation/test_refinements_validation.py @@ -207,3 +207,74 @@ def test_snappy_body_refinement_validator(): snappy.BodyRefinement( bodies=SnappyBody(name="body1", surfaces=[Surface(name="surface")]), gap_resolution=2 * u.mm ) + + +def test_snappy_proximity_spacing_error_when_exceeds_default_min_spacing(): + """When min_spacing is not set on a BodyRefinement but proximity_spacing exceeds + defaults.min_spacing, a ValueError should be raised.""" + message = "Proximity spacing for a BodyRefinement (5.0 mm) was set higher than the minimal spacing (3.0 mm)." + with SI_unit_system, pytest.raises(pd.ValidationError, match=re.escape(message)): + snappy.SurfaceMeshingParams( + defaults=snappy.SurfaceMeshingDefaults( + min_spacing=3 * u.mm, max_spacing=10 * u.mm, gap_resolution=0.1 * u.mm + ), + refinements=[ + snappy.BodyRefinement( + bodies=SnappyBody(name="body1", surfaces=[Surface(name="surface")]), + proximity_spacing=5 * u.mm, + max_spacing=10 * u.mm, + ), + ], + ) + + +def test_snappy_proximity_spacing_ok_when_below_default_min_spacing(): + """When proximity_spacing is already <= defaults.min_spacing, no error should be raised.""" + with SI_unit_system: + body = SnappyBody(name="body1", surfaces=[Surface(name="surface")]) + params = snappy.SurfaceMeshingParams( + defaults=snappy.SurfaceMeshingDefaults( + min_spacing=3 * u.mm, max_spacing=10 * u.mm, gap_resolution=0.1 * u.mm + ), + refinements=[ + snappy.BodyRefinement( + bodies=body, + proximity_spacing=2 * u.mm, + max_spacing=10 * u.mm, + ), + ], + ) + assert params.refinements[0].proximity_spacing == 2 * u.mm + + +def test_snappy_proximity_spacing_error_with_explicit_min_spacing(): + """When both min_spacing and proximity_spacing are set on the refinement + and proximity_spacing > min_spacing, the entity-level validator raises.""" + message = "Proximity spacing (6.0 mm) was set higher than the minimal spacing (4.0 mm)." + with SI_unit_system, pytest.raises(pd.ValidationError, match=re.escape(message)): + snappy.BodyRefinement( + bodies=SnappyBody(name="body1", surfaces=[Surface(name="surface")]), + min_spacing=4 * u.mm, + proximity_spacing=6 * u.mm, + max_spacing=10 * u.mm, + ) + + +def test_snappy_proximity_spacing_ok_when_min_spacing_is_set(): + """When min_spacing is explicitly set and proximity_spacing <= min_spacing, no error.""" + with SI_unit_system: + body = SnappyBody(name="body1", surfaces=[Surface(name="surface")]) + params = snappy.SurfaceMeshingParams( + defaults=snappy.SurfaceMeshingDefaults( + min_spacing=1 * u.mm, max_spacing=10 * u.mm, gap_resolution=0.1 * u.mm + ), + refinements=[ + snappy.BodyRefinement( + bodies=body, + min_spacing=4 * u.mm, + proximity_spacing=3 * u.mm, + max_spacing=10 * u.mm, + ), + ], + ) + assert params.refinements[0].proximity_spacing == 3 * u.mm