Skip to content
Open
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
29 changes: 27 additions & 2 deletions flow360/component/simulation/meshing_param/volume_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,32 @@ class RotationCylinder(RotationVolume):
entities: EntityList[Cylinder] = pd.Field()


class AutomatedFarfield(Flow360BaseModel):
class _FarfieldBase(Flow360BaseModel):
"""Base class for farfield parameters."""

enforced_half_model: Optional[Literal["+y", "-y"]] = (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to enforce_half_model?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This choice means that if we want to enforce full-body in the future, we'll have to change this interface again. Isn't using the enum approach more future-proof, since then we just have to deprecate the "auto" option for the domain_type?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about "enforce_domain_type"? "enforce" as we are overriding the default behavior and changing the geometry/surface mesh?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I like it. Let's do enforce_domain_type as the parameter name. What about the options?

  • full_body
  • half_body_positive_y
  • half_body_negative_y

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need auto option since this parameter is Optional. In the future we just need to make it required then?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to think more since in the future if we deprecate "auto" then there is nothing we are "enforcing" against? I guess against "auto symmetry" instead of "cut symmetry"?

Maybe it is best to just call "domain_type"...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah good point. Maybe domain_type is just clearer. In the description we can say that this option is meant to override the "auto symmetry" behavior for now.

pd.Field( # In the future, we will support more half model types via Union.
None,
description="If set, trim to a half-model by slicing the geometry with the global Y=0 plane; "
"keep the '+y' or '-y' side for meshing and simulation.",
)
)

@pd.field_validator("enforced_half_model", mode="after")
@classmethod
def _validate_only_in_beta_mesher(cls, value):
"""
Ensure that enforced_half_model objects are only processed with the beta mesher.
"""
validation_info = get_validation_info()
if validation_info is None:
return value
if not value:
return value
raise ValueError("`enforced_half_model` is only supported with the beta mesher.")


class AutomatedFarfield(_FarfieldBase):
"""
Settings for automatic farfield volume zone generation.

Expand Down Expand Up @@ -412,7 +437,7 @@ def _validate_quasi_3d_periodic_only_in_legacy_mesher(cls, values):
return values


class UserDefinedFarfield(Flow360BaseModel):
class UserDefinedFarfield(_FarfieldBase):
"""
Setting for user defined farfield zone generation.
This means the "farfield" boundaries are coming from the supplied geometry file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,17 @@ def _get_surface_refinements(refinement_list: list[dict]):
]


def _get_volume_zones(volume_zones_list: list[dict]):
"""
Get the volume zones from the input_params.
"""
return [
item
for item in volume_zones_list
if item["type"] in ("AutomatedFarfield", "UserDefinedFarfield")
]


GAI_SETTING_WHITELIST = {
"meshing": {
"defaults": {
Expand All @@ -159,6 +170,7 @@ def _get_surface_refinements(refinement_list: list[dict]):
"surface_max_adaptation_iterations": None,
},
"refinements": _get_surface_refinements,
"volume_zones": _get_volume_zones,
},
"private_attribute_asset_cache": {
"project_entity_info": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ def get_volume_meshing_json(input_params: SimulationParams, mesh_units):
for zone in input_params.meshing.volume_zones:
if isinstance(zone, UserDefinedFarfield):
translated["farfield"] = {"type": "user-defined"}
if zone.enforced_half_model is not None:
translated["farfield"]["enforcedHalfModel"] = zone.enforced_half_model
break

if isinstance(zone, AutomatedFarfield):
Expand All @@ -272,6 +274,9 @@ def get_volume_meshing_json(input_params: SimulationParams, mesh_units):
translated["farfield"]["periodic"] = {"type": "translational"}
else:
translated["farfield"]["type"] = zone.method

if zone.enforced_half_model is not None:
translated["farfield"]["enforcedHalfModel"] = zone.enforced_half_model
break

if "farfield" not in translated:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -454,3 +454,13 @@ def test_quasi_3d_periodic_only_in_legacy_mesher():
# does not raise with legacy mesher on
with ValidationContext(VOLUME_MESH, non_beta_mesher_context):
my_farfield = AutomatedFarfield(method="quasi-3d-periodic")


def test_enforced_half_model_only_in_beta_mesher():
# raises when beta mesher is off
with pytest.raises(
pd.ValidationError,
match=r"`enforced_half_model` is only supported with the beta mesher.",
):
with ValidationContext(VOLUME_MESH, non_beta_mesher_context):
AutomatedFarfield(enforced_half_model="+y")
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,15 @@
"units": "flow360_length_unit"
}
}
],
"volume_zones": [
{
"enforced_half_model": "+y",
"type": "AutomatedFarfield",
"name": "Automated Farfield",
"method": "auto",
"relative_size": 50.0
}
]
},
"private_attribute_asset_cache": {
Expand Down Expand Up @@ -631,4 +640,4 @@
]
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ def test_gai_surface_mesher_refinements():
)
geometry["cube-holes.egads"].transformation = transformation
geometry["cylinder.stl"].transformation = transformation
farfield = AutomatedFarfield()
farfield = AutomatedFarfield(enforced_half_model="+y")
params = SimulationParams(
meshing=MeshingParams(
defaults=MeshingDefaults(
Expand Down
4 changes: 2 additions & 2 deletions tests/simulation/translator/test_volume_meshing_translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def get_test_param():
Surface(name="interface2"),
],
),
UserDefinedFarfield(),
UserDefinedFarfield(enforced_half_model="-y"),
RotationVolume(
name="we_do_not_use_this_anyway",
entities=inner_cylinder,
Expand Down Expand Up @@ -248,7 +248,7 @@ def test_param_to_json(get_test_param, get_surface_mesh):

ref_dict = {
"refinementFactor": 1.45,
"farfield": {"type": "user-defined"},
"farfield": {"type": "user-defined", "enforcedHalfModel": "-y"},
"volume": {
"firstLayerThickness": 1.35e-06,
"growthRate": 1.04,
Expand Down
Loading