Skip to content
Draft
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
17 changes: 9 additions & 8 deletions flow360/component/simulation/entity_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,15 +367,16 @@ def get_registry(self, internal_registry, **_) -> EntityRegistry:
"face", face_group_tag, registry=internal_registry
)

if self.edge_group_tag is None:
edge_group_tag = self._get_default_grouping_tag("edge")
log.info(f"Using `{edge_group_tag}` as default grouping for edges.")
else:
edge_group_tag = self.edge_group_tag
if len(self.edge_ids) > 0:
if self.edge_group_tag is None:
edge_group_tag = self._get_default_grouping_tag("edge")
log.info(f"Using `{edge_group_tag}` as default grouping for edges.")
else:
edge_group_tag = self.edge_group_tag

internal_registry = self._group_entity_by_tag(
"edge", edge_group_tag, registry=internal_registry
)
internal_registry = self._group_entity_by_tag(
"edge", edge_group_tag, registry=internal_registry
)

if self.body_attribute_names:
# Post-25.5 geometry asset. For Pre 25.5 we just skip body grouping.
Expand Down
151 changes: 151 additions & 0 deletions flow360/component/simulation/meshing_param/params.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
)
from flow360.component.simulation.validation.validation_utils import EntityUsageMap

from flow360.component.simulation.entity_info import Surface
from flow360.component.simulation.framework.entity_base import EntityList

RefinementTypes = Annotated[
Union[
SurfaceEdgeRefinement,
Expand Down Expand Up @@ -178,6 +181,150 @@ def invalid_geometry_accuracy(cls, value):
return value


class MeshQuality(Flow360BaseModel):
"""
Mesh quality settings for the surface mesh generation.
"""

max_non_ortho: float = pd.Field(
85,
description="Maximum non-orthogonality allowed in the mesh.",
)

max_boundary_skewness: float = pd.Field(
20,
description="Maximum boundary skewness allowed in the mesh.",
)

max_internal_skewness: float = pd.Field(
50,
description="Maximum internal skewness allowed in the mesh.",
)

max_concave: float = pd.Field(
50,
description="Maximum concavity allowed in the mesh.",
)

min_vol: float = pd.Field(
-1e+30,
description="Minimum volume allowed in the mesh.",
)

min_tet_quality: float = pd.Field(
-1e+30,
description="Minimum tetrahedral quality allowed in the mesh.",
)

min_area: float = pd.Field(
-1,
description="Minimum area allowed in the mesh.",
)

min_twist: float = pd.Field(
-2,
description="Minimum twist allowed in the mesh.",
)

min_determinant: float = pd.Field(
0,
description="Minimum determinant allowed in the mesh.",
)

min_vol_ratio: float = pd.Field(
0,
description="Minimum volume ratio allowed in the mesh.",
)

min_face_weight: float = pd.Field(
0,
description="Minimum face weight allowed in the mesh.",
)

min_triangle_twist: float = pd.Field(
-1,
description="Minimum triangle twist allowed in the mesh.",
)

n_smooth_scale: int = pd.Field(
4,
description="Number of smoothing scale iterations.",
)

error_reduction: float = pd.Field(
0.75,
description="Error reduction factor for mesh smoothing.",
)

min_vol_collapse_ratio: float = pd.Field(
0,
description="Minimum volume collapse ratio allowed in the mesh.",
)

class SnapControls(Flow360BaseModel):
"""
Snap controls for the surface mesh generation.
"""

tolerance: Optional[pd.PositiveFloat] = pd.Field(
2,
description="Tolerance for the surface mesh generation.",
)

n_feature_snap_iter: int = pd.Field(
15,
description="Number of feature snap iterations.",
)
multi_region_feature_snap: bool = pd.Field(
True,
description="Whether to use multi-region feature snap.",
)

class GeometrySettings(Flow360BaseModel):
"""
Geometry settings for the surface mesh generation.
"""

entities: EntityList[Surface] = pd.Field(
default=[],
description="List of entities to be wrapped.",
)

spec: dict = pd.Field(
default={},
description="Specification for the geometry settings. Example: "
'{"spacing": {"min": 5, "max": 50}, '
'"edges": {"edgeSpacing": 2, "includedAngle": 140, "minElem": 3, "minLen": 10}, '
'"gap": 0.001, "regions": [], "gapSpacingReduction": null, "includedAngle": 140}',
)



class WrappingSettings(Flow360BaseModel):
geometry: Optional[List[GeometrySettings]] = pd.Field(
default=None,
description="List of settings geometry entities to be wrapped.",
)

mesh_quality: MeshQuality = pd.Field(
MeshQuality(),
description="Mesh quality settings for the surface mesh generation.",
)

snap_controls: SnapControls = pd.Field(
SnapControls(),
description="Snap controls for the surface mesh generation.",
)
location_in_mesh: Optional[LengthType.Point] = pd.Field(
None,
description="Point in the mesh that will be used to determine side for wrapping.",
)
cad_is_fluid: Optional[bool] = pd.Field(
False,
description="Whether the CAD represents a fluid or solid.",
)


class MeshingParams(Flow360BaseModel):
"""
Meshing parameters for volume and/or surface mesher. This contains all the meshing related settings.
Expand Down Expand Up @@ -243,6 +390,10 @@ class MeshingParams(Flow360BaseModel):
default=None, description="Creation of new volume zones."
)

wrapping_settings: Optional[WrappingSettings] = pd.Field(
default=None, description="Wrapping settings for the surface mesh generation."
)

@pd.field_validator("volume_zones", mode="after")
@classmethod
def _check_volume_zones_has_farfied(cls, v):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,29 @@ def get_surface_meshing_json(input_params: SimulationParams, mesh_units):
for face_id in surface.private_attribute_sub_components:
translated["boundaries"][face_id] = {"boundaryName": surface.name}



##:: >> Step 7: Get wrapping settings (for snappy)
if input_params.meshing.wrapping_settings is not None:
translated["meshingMethod"] = "wrapping"
translated["geometry"] = {
"bodies": []
}
for geometry_settings in input_params.meshing.wrapping_settings.geometry:
for entity in geometry_settings.entities.stored_entities:
translated["geometry"]["bodies"].append({
"bodyName": entity.name,
**geometry_settings.spec
})
translated["mesherSettings"] = {
"snappyHexMesh": {
"snapControls": input_params.meshing.wrapping_settings.snap_controls.model_dump(by_alias=True),
},
"meshQuality": input_params.meshing.wrapping_settings.mesh_quality.model_dump(by_alias=True),
}
location_in_mesh = input_params.meshing.wrapping_settings.location_in_mesh
if location_in_mesh is not None:
translated["locationInMesh"] = location_in_mesh.value.tolist()
translated["cadIsFluid"] = input_params.meshing.wrapping_settings.cad_is_fluid

return translated
Loading
Loading