[FXC-5449] allow varying refinements on axisymmetric body faces#1882
[FXC-5449] allow varying refinements on axisymmetric body faces#1882alexxu-flex wants to merge 14 commits intomainfrom
Conversation
…ying-refinement-faces
…ying-refinement-faces
…ying-refinement-faces
| ... entities=[cylinder, box, axisymmetric_body, sphere], | ||
| ... spacing=1*fl.u.cm | ||
| ... spacing=1*fl.u.cm, | ||
| ... face_spacing={ |
There was a problem hiding this comment.
This is too nested and confusing. We need to redesign the interface.
There was a problem hiding this comment.
//User interface
face_spacing={
axisymmetric_body.segments[1] : 0.2*fl.u.cm
}
// Storage side
"face_spacing":{
("entioty_id":"$axisymmetric_body.private_attribute_id", "segment_index": 1) : {"value": 0.2, "units":"cm"}
}
There was a problem hiding this comment.
Then you need a Pydantic model for the "segment" class.
It will be similar relationship between Windtunnel farfield and the windtunnel ghost surfaces.
class Segment(BaseModel):
type_name:Literal["Segment"]
entity_id:str
segment_index: int =pd.Field(min=..., )…ying-refinement-faces
…ying-refinement-faces
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 3 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| for key, val in value.items(): | ||
| if isinstance(key, Face): | ||
| result.setdefault(key.entity_name, {})[key.index] = val | ||
| elif isinstance(key, str) and isinstance(val, dict): |
There was a problem hiding this comment.
Face overrides lose entity identity
Medium Severity
face_spacing converts Face keys using only entity_name, dropping Face.entity_id. This makes overrides ambiguous when multiple AxisymmetricBody objects share a name, and stale Face references from a different entity with the same name are silently accepted. Translation then applies spacing by name, so overrides can target the wrong body.
Additional Locations (2)
| for entity in self.entities.stored_entities: | ||
| if isinstance(entity, AxisymmetricBody): | ||
| entity_map[entity.name] = entity | ||
|
|
There was a problem hiding this comment.
Selector entities rejected in face spacing validation
Medium Severity
check_face_spacing builds entity_map from self.entities.stored_entities only. When UniformRefinement.entities is provided via selectors, stored_entities can be empty before expansion, so valid face_spacing entries are rejected as “not an AxisymmetricBody in this refinement’s entities list.”
| elif isinstance(key, str) and isinstance(val, dict): | ||
| # Already in {name: {idx: spacing}} format (e.g., from JSON deserialization) | ||
| result[key] = {int(k): v for k, v in val.items()} | ||
| else: |
There was a problem hiding this comment.
Mixed key formats drop face overrides
Low Severity
_convert_face_spacing silently overwrites entries when face_spacing mixes Face keys and serialized string keys for the same entity. The str branch assigns result[key] = ..., replacing previously accumulated per-face values from Face keys, so some overrides are lost without validation errors.
Additional Locations (1)
|
|
||
|
|
||
| @final | ||
| class Face(pd.BaseModel): |
There was a problem hiding this comment.
Face will be reserved for geometry concepts. It is a reserved word.
| "profile_curve[i] and profile_curve[i+1]. Faces without overrides use the default `spacing`.", | ||
| ) | ||
|
|
||
| @pd.field_validator("face_spacing", mode="before") |
There was a problem hiding this comment.
Let's not use before validators unless really necessary.
Why don't we do this instead?
face_spacing: Optional[Dict[AxisSymmetricSegment, LengthType.Positive]] = pd.Field(And then we have:
class AxisSymmetricSegment(Flow360BaseModel):
entity_id: str
segment_index: pd.PositiveIntso the axisymmetric_body.face(2) returns an AxisSymmetricSegment instance?
Then we do not need this complicate and fragile before validator?
|
|
||
| return self | ||
|
|
||
| @pd.model_validator(mode="after") |
There was a problem hiding this comment.
make this a contextual validator. You can then retrieve the axisymmetric body instance by querying the entity registry.
Take a look at param_info.get_entity_registry() and registry.find_by_type_name_and_id()


Note
Medium Risk
Medium risk because it changes meshing parameter validation and translation output for
UniformRefinement, which could alter generated volume-meshing JSON for axisymmetric cases. Scope is localized and covered by new unit/translator tests.Overview
Enables per-face uniform refinement spacing overrides on
AxisymmetricBodyviaUniformRefinement.face_spacing, keyed bybody.face(i)and validated against the refinement’s entities and profile-curve face count.Introduces a new immutable
Facereference type andAxisymmetricBody.face()helper, updates preprocessing to recursively unit-convert values inside nested dicts as well as lists, and extends the volume-meshing translator to emit densefaceSpacingsarrays for axisymmetric refinements (with round-trip serialization tests).Written by Cursor Bugbot for commit 200f6b4. This will update automatically on new commits. Configure here.