Skip to content
21 changes: 20 additions & 1 deletion flow360/component/simulation/meshing_param/volume_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ class AutomatedFarfield(Flow360BaseModel):

type: Literal["AutomatedFarfield"] = pd.Field("AutomatedFarfield", frozen=True)
name: Optional[str] = pd.Field("Automated Farfield") # Kept optional for backward compatibility
method: Literal["auto", "quasi-3d"] = pd.Field(
method: Literal["auto", "quasi-3d", "quasi-3d-periodic"] = pd.Field(
default="auto",
frozen=True,
description="""
Expand All @@ -364,6 +364,7 @@ class AutomatedFarfield(Flow360BaseModel):
- -Y semi sphere if min{Y} < 0 and max{Y} = 0.
- quasi-3d: Thin disk will be generated for quasi 3D cases.
Both sides of the farfield disk will be treated as "symmetric plane"
- quasi-3d-periodic: The two sides of the quasi-3d disk will be conformal
Note: For quasi-3d, please do not group patches from both sides of the farfield disk into a single surface.
""",
)
Expand All @@ -372,6 +373,11 @@ class AutomatedFarfield(Flow360BaseModel):
frozen=True,
exclude=True,
)
relative_size: pd.PositiveFloat = pd.Field(
default=50.0,
description="Radius of the far-field (semi)sphere/cylinder relative to "
"the max dimension of the geometry bounding box.",
)

@property
def farfield(self):
Expand All @@ -392,6 +398,19 @@ def symmetry_planes(self):
]
raise ValueError(f"Unsupported method: {self.method}")

@pd.field_validator("method", mode="after")
@classmethod
def _validate_quasi_3d_periodic_only_in_legacy_mesher(cls, values):
"""
Check mesher and AutomatedFarfield method compatibility
"""
validation_info = get_validation_info()
if validation_info is None:
return values
if validation_info.is_beta_mesher and values == "quasi-3d-periodic":
raise ValueError("Only legacy mesher can support quasi-3d-periodic")
return values


class UserDefinedFarfield(Flow360BaseModel):
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,13 @@ def get_volume_meshing_json(input_params: SimulationParams, mesh_units):

if isinstance(zone, AutomatedFarfield):
translated["farfield"] = {
"type": zone.method,
"planarFaceTolerance": meshing_params.defaults.planar_face_tolerance,
"planarFaceTolerance": meshing_params.defaults.planar_face_tolerance
}
if zone.method == "quasi-3d-periodic":
translated["farfield"]["type"] = "quasi-3d"
translated["farfield"]["periodic"] = {"type": "translational"}
else:
translated["farfield"]["type"] = zone.method
break

if "farfield" not in translated:
Expand Down
3 changes: 2 additions & 1 deletion tests/ref/simulation/service_init_geometry.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
{
"type": "AutomatedFarfield",
"name": "Farfield",
"method": "auto"
"method": "auto",
"relative_size": 50.0
}
]
},
Expand Down
3 changes: 2 additions & 1 deletion tests/ref/simulation/service_init_surface_mesh.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
{
"type": "AutomatedFarfield",
"name": "Farfield",
"method": "auto"
"method": "auto",
"relative_size": 50.0
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,3 +440,17 @@ def test_box_entity_enclosed_only_in_beta_mesher():
spacing_circumferential=20,
enclosed_entities=[box_entity],
)


def test_quasi_3d_periodic_only_in_legacy_mesher():
# raises when legacy mesher is off
with pytest.raises(
pd.ValidationError,
match=r"Only legacy mesher can support quasi-3d-periodic",
):
with ValidationContext(VOLUME_MESH, beta_mesher_context):
my_farfield = AutomatedFarfield(method="quasi-3d-periodic")

# does not raise with legacy mesher on
with ValidationContext(VOLUME_MESH, non_beta_mesher_context):
my_farfield = AutomatedFarfield(method="quasi-3d-periodic")
Loading