Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions flow360/component/simulation/meshing_param/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,42 @@ def invalid_geometry_accuracy(cls, value):
raise ValueError("Geometry accuracy is required when geometry AI is used.")
return value

@pd.field_validator("geometry_accuracy", mode="after")
@classmethod
def compatible_geometry_accuracy_and_planar_face_tolerance(cls, value):
"""Ensure geometry accuracy and planar face tolerance are compatible"""
if value is None:
return value

validation_info = get_validation_info()

if (
validation_info is None
or validation_info.planar_face_tolerance is None
or validation_info.global_bounding_box is None
or validation_info.project_length_unit is None
):
return value

absolute_tolerance_dimensioned = (
validation_info.global_bounding_box.largest_dimension
* validation_info.planar_face_tolerance
* validation_info.project_length_unit
)
if value > absolute_tolerance_dimensioned:
minimum_planar_face_tolerance = (
value
/ validation_info.project_length_unit
/ validation_info.global_bounding_box.largest_dimension
).value
raise ValueError(
f"geometry_accuracy is too large for the planar_face_tolerance to take effect."
f" Reduce geometry_accuracy to at most {absolute_tolerance_dimensioned} "
f"or increase the planar_face_tolerance to at least {minimum_planar_face_tolerance}."
)

return value

@pd.field_validator(
"surface_max_aspect_ratio", "surface_max_adaptation_iterations", mode="after"
)
Expand Down
57 changes: 57 additions & 0 deletions tests/simulation/params/test_validators_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import flow360.component.simulation.units as u
from flow360.component.simulation.entity_info import (
GeometryEntityInfo,
SurfaceMeshEntityInfo,
VolumeMeshEntityInfo,
)
Expand Down Expand Up @@ -1843,6 +1844,7 @@ def test_beta_mesher_only_features():


def test_geometry_AI_only_features():
# * Test GAI guardrails
with SI_unit_system:
params = SimulationParams(
meshing=MeshingParams(
Expand Down Expand Up @@ -1903,6 +1905,61 @@ def test_geometry_AI_only_features():
errors[0]["msg"] == "Value error, Geometry accuracy is required when geometry AI is used."
)

# * Test geometry_accuracy and planar_face_tolerance compatibility
with SI_unit_system:
params_original = SimulationParams(
meshing=MeshingParams(
defaults=MeshingDefaults(
geometry_accuracy=1e-5 * u.m,
planar_face_tolerance=1e-10,
boundary_layer_first_layer_thickness=10,
surface_max_edge_length=1e-2,
),
),
private_attribute_asset_cache=AssetCache(
project_length_unit=1 * u.cm,
use_inhouse_mesher=True,
use_geometry_AI=True,
project_entity_info=GeometryEntityInfo(
global_bounding_box=[[-100, -100, -100], [100, 1e-12, 100]],
),
),
)
params, errors, _ = validate_model(
params_as_dict=params_original.model_dump(mode="json"),
validated_by=ValidationCalledBy.LOCAL,
root_item_type="Geometry",
validation_level="VolumeMesh",
)
assert len(errors) == 1
# Largest dim = 200 cm
# with planar face tolerance = 1e-10
# largest geometry accuracy = 1e-10 * 200 cm = 2e-8 cm
# with geometry accuracy = 1e-5m
# minimum planar face tolerance = 1e-5m / 200 cm = 5e-06
assert errors[0]["msg"] == (
"Value error, geometry_accuracy is too large for the planar_face_tolerance to take effect. "
"Reduce geometry_accuracy to at most 2e-08 cm or increase the planar_face_tolerance to at least 5e-06."
)
params_original.meshing.defaults.geometry_accuracy = 2e-08 * u.cm
params, _, _ = validate_model(
params_as_dict=params_original.model_dump(mode="json"),
validated_by=ValidationCalledBy.LOCAL,
root_item_type="Geometry",
validation_level="VolumeMesh",
)
assert params

params_original.meshing.defaults.geometry_accuracy = 1e-5 * u.m
params_original.meshing.defaults.planar_face_tolerance = 5e-06
params, _, _ = validate_model(
params_as_dict=params_original.model_dump(mode="json"),
validated_by=ValidationCalledBy.LOCAL,
root_item_type="Geometry",
validation_level="VolumeMesh",
)
assert params


def test_redefined_user_defined_fields():

Expand Down
Loading