Skip to content

Commit

Permalink
fix(): add update mechanism for input cache (#626)
Browse files Browse the repository at this point in the history
* fix(): add update mechanism for input cache

* More unit tests

* Fix unit test

* Refactor to reduce number of validators

* Reverted placement of private_attribute_input_cache
  • Loading branch information
benflexcompute committed Dec 16, 2024
1 parent c617c16 commit a5f86fb
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ class GenericReferenceCondition(MultiConstructorBaseModel):
velocity_magnitude: Optional[VelocityType.Positive] = ConditionalField(
context=CASE,
description="Freestream velocity magnitude. Used as reference velocity magnitude"
+ " when :py:attr:`reference_velocity_magnitude` is not specified.",
+ " when :py:attr:`reference_velocity_magnitude` is not specified. Cannot change once specified.",
frozen=True,
)
thermal_state: ThermalState = pd.Field(
ThermalState(),
Expand All @@ -233,6 +234,12 @@ def mach(self) -> pd.PositiveFloat:
"""Computes Mach number."""
return self.velocity_magnitude / self.thermal_state.speed_of_sound

@pd.field_validator("thermal_state", mode="after")
@classmethod
def _update_input_cache(cls, value, info: pd.ValidationInfo):
setattr(info.data["private_attribute_input_cache"], info.field_name, value)
return value


class AerospaceConditionCache(Flow360BaseModel):
"""[INTERNAL] Cache for AerospaceCondition inputs"""
Expand Down Expand Up @@ -275,6 +282,7 @@ class AerospaceCondition(MultiConstructorBaseModel):
description="Freestream velocity magnitude. Used as reference velocity magnitude"
+ " when :py:attr:`reference_velocity_magnitude` is not specified.",
context=CASE,
frozen=True,
)
thermal_state: ThermalState = pd.Field(
ThermalState(),
Expand All @@ -284,6 +292,7 @@ class AerospaceCondition(MultiConstructorBaseModel):
reference_velocity_magnitude: Optional[VelocityType.Positive] = CaseField(
None,
description="Reference velocity magnitude. Is required when :py:attr:`velocity_magnitude` is 0.",
frozen=True,
)
private_attribute_input_cache: AerospaceConditionCache = AerospaceConditionCache()

Expand Down Expand Up @@ -381,6 +390,12 @@ def mach(self) -> pd.PositiveFloat:
"""Computes Mach number."""
return self.velocity_magnitude / self.thermal_state.speed_of_sound

@pd.field_validator("alpha", "beta", "thermal_state", mode="after")
@classmethod
def _update_input_cache(cls, value, info: pd.ValidationInfo):
setattr(info.data["private_attribute_input_cache"], info.field_name, value)
return value


# pylint: disable=fixme
# TODO: AutomotiveCondition
Expand Down
22 changes: 18 additions & 4 deletions flow360/component/simulation/primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,16 +264,24 @@ class Box(MultiConstructorBaseModel, _VolumeEntityBase):
"""

type_name: Literal["Box"] = pd.Field("Box", frozen=True)
private_attribute_entity_type_name: Literal["Box"] = pd.Field("Box", frozen=True)
# pylint: disable=no-member
center: LengthType.Point = pd.Field(description="The coordinates of the center of the box.")
size: LengthType.PositiveVector = pd.Field(
description="The dimensions of the box (length, width, height)."
)
axis_of_rotation: Axis = pd.Field(default=(0, 0, 1), description="The rotation axis.")
angle_of_rotation: AngleType = pd.Field(default=0 * u.degree, description="The rotation angle.")
private_attribute_input_cache: BoxCache = pd.Field(BoxCache(), frozen=True)
axis_of_rotation: Axis = pd.Field(
default=(0, 0, 1),
description="The rotation axis. Cannot change once specified.",
frozen=True,
)
angle_of_rotation: AngleType = pd.Field(
default=0 * u.degree,
description="The rotation angle. Cannot change once specified.",
frozen=True,
)
private_attribute_id: str = pd.Field(default_factory=generate_uuid, frozen=True)
private_attribute_input_cache: BoxCache = pd.Field(BoxCache(), frozen=True)
private_attribute_entity_type_name: Literal["Box"] = pd.Field("Box", frozen=True)

# pylint: disable=no-self-argument
@MultiConstructorBaseModel.model_constructor
Expand Down Expand Up @@ -344,6 +352,12 @@ def axes(self):
"""Return the axes that the box is aligned with."""
return self.private_attribute_input_cache.axes

@pd.field_validator("center", "size", mode="after")
@classmethod
def _update_input_cache(cls, value, info: pd.ValidationInfo):
setattr(info.data["private_attribute_input_cache"], info.field_name, value)
return value


@final
class Cylinder(_VolumeEntityBase):
Expand Down
42 changes: 41 additions & 1 deletion tests/ref/simulation/service_init_geometry.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,47 @@
"operating_condition": {
"type_name": "AerospaceCondition",
"private_attribute_constructor": "default",
"private_attribute_input_cache": {},
"private_attribute_input_cache": {
"alpha": {
"value": 0.0,
"units": "degree"
},
"beta": {
"value": 0.0,
"units": "degree"
},
"thermal_state": {
"type_name": "ThermalState",
"private_attribute_constructor": "default",
"private_attribute_input_cache": {},
"temperature": {
"value": 288.15,
"units": "K"
},
"density": {
"value": 1.225,
"units": "kg/m**3"
},
"material": {
"type": "air",
"name": "air",
"dynamic_viscosity": {
"reference_viscosity": {
"value": 1.716e-05,
"units": "Pa*s"
},
"reference_temperature": {
"value": 273.15,
"units": "K"
},
"effective_temperature": {
"value": 110.4,
"units": "K"
}
}
}
}
},
"alpha": {
"value": 0.0,
"units": "degree"
Expand Down
42 changes: 41 additions & 1 deletion tests/ref/simulation/service_init_volume_mesh.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,47 @@
"operating_condition": {
"type_name": "AerospaceCondition",
"private_attribute_constructor": "default",
"private_attribute_input_cache": {},
"private_attribute_input_cache": {
"alpha": {
"value": 0.0,
"units": "degree"
},
"beta": {
"value": 0.0,
"units": "degree"
},
"thermal_state": {
"type_name": "ThermalState",
"private_attribute_constructor": "default",
"private_attribute_input_cache": {},
"temperature": {
"value": 288.15,
"units": "K"
},
"density": {
"value": 1.225,
"units": "kg/m**3"
},
"material": {
"type": "air",
"name": "air",
"dynamic_viscosity": {
"reference_viscosity": {
"value": 1.716e-05,
"units": "Pa*s"
},
"reference_temperature": {
"value": 273.15,
"units": "K"
},
"effective_temperature": {
"value": 110.4,
"units": "K"
}
}
}
}
},
"alpha": {
"value": 0.0,
"units": "degree"
Expand Down
28 changes: 28 additions & 0 deletions tests/simulation/framework/test_multi_constructor_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,31 @@ class ModelWithEntityList(Flow360BaseModel):

data_parsed = parse_model_dict(incomplete_data, globals())
assert sorted(data_parsed.items()) == sorted(full_data.items())


def test_entity_modification(get_aerospace_condition_using_from):

my_box = Box.from_principal_axes(
name="box",
axes=[(0, 1, 0), (0, 0, 1)],
center=(0, 0, 0) * u.m,
size=(0.2, 0.3, 2) * u.m,
)

my_box.center = (1, 2, 3) * u.m
assert all(my_box.private_attribute_input_cache.center == (1, 2, 3) * u.m)

my_box = Box(
name="box2",
axis_of_rotation=(1, 0, 0),
angle_of_rotation=45 * u.deg,
center=(1, 1, 1) * u.m,
size=(0.2, 0.3, 2) * u.m,
)

my_box.size = (1, 2, 32) * u.m
assert all(my_box.private_attribute_input_cache.size == (1, 2, 32) * u.m)

my_op = get_aerospace_condition_using_from
my_op.alpha = -12 * u.rad
assert my_op.private_attribute_input_cache.alpha == -12 * u.rad

0 comments on commit a5f86fb

Please sign in to comment.