From 311f217bdd8bcd6c886c10f8734f0e703565c647 Mon Sep 17 00:00:00 2001 From: Ben <106089368+benflexcompute@users.noreply.github.com> Date: Thu, 9 Apr 2026 14:38:23 -0400 Subject: [PATCH] fix(): Fix coordinate transformation writes to frozen BETDisk fields (#1979) --- .../component/simulation/translator/utils.py | 16 +++- .../translator/test_translation_utils.py | 87 +++++++++++++++++++ 2 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 tests/simulation/translator/test_translation_utils.py diff --git a/flow360/component/simulation/translator/utils.py b/flow360/component/simulation/translator/utils.py index 534a5fe65..133a4645e 100644 --- a/flow360/component/simulation/translator/utils.py +++ b/flow360/component/simulation/translator/utils.py @@ -123,9 +123,19 @@ def _apply_transformations_to_model( setattr(model, field_name, new_entity_list) elif isinstance(field_value, (list, tuple)): - new_items = [_transform_sequence_item(item, manager) for item in field_value] - new_value = new_items if isinstance(field_value, list) else tuple(new_items) - setattr(model, field_name, new_value) + transformed_items = None + for index, item in enumerate(field_value): + transformed = _transform_sequence_item(item, manager) + if transformed is not item: + if transformed_items is None: + transformed_items = list(field_value) + transformed_items[index] = transformed + + if transformed_items is not None: + new_value = ( + transformed_items if isinstance(field_value, list) else tuple(transformed_items) + ) + setattr(model, field_name, new_value) elif isinstance(field_value, Flow360BaseModel): _apply_transformations_to_model(field_value, manager) diff --git a/tests/simulation/translator/test_translation_utils.py b/tests/simulation/translator/test_translation_utils.py new file mode 100644 index 000000000..8066314b6 --- /dev/null +++ b/tests/simulation/translator/test_translation_utils.py @@ -0,0 +1,87 @@ +import flow360.component.simulation.units as u +from flow360.component.simulation.draft_context.coordinate_system_manager import ( + CoordinateSystemAssignmentGroup, + CoordinateSystemEntityRef, + CoordinateSystemStatus, +) +from flow360.component.simulation.entity_operation import CoordinateSystem +from flow360.component.simulation.framework.param_utils import AssetCache +from flow360.component.simulation.models.volume_models import ( + BETDisk, + BETDiskChord, + BETDiskSectionalPolar, + BETDiskTwist, +) +from flow360.component.simulation.primitives import Cylinder +from flow360.component.simulation.simulation_params import SimulationParams +from flow360.component.simulation.translator.utils import ( + apply_coordinate_system_transformations, +) +from flow360.component.simulation.unit_system import SI_unit_system + + +def test_apply_coordinate_system_transformations_skips_frozen_non_entity_sequences(): + with SI_unit_system: + cylinder = Cylinder( + name="bet_disk", + center=(0, 0, 0) * u.m, + axis=(0, 0, 1), + height=1 * u.m, + outer_radius=1 * u.m, + ) + bet_disk = BETDisk( + entities=cylinder, + rotation_direction_rule="leftHand", + number_of_blades=3, + omega=100 * u.rpm, + chord_ref=1 * u.m, + n_loading_nodes=20, + mach_numbers=[0], + reynolds_numbers=[1000000], + twists=[BETDiskTwist(radius=0 * u.m, twist=0 * u.deg)], + chords=[BETDiskChord(radius=0 * u.m, chord=1 * u.m)], + alphas=[-2, 0, 2] * u.deg, + sectional_radiuses=[0.25, 0.5] * u.m, + sectional_polars=[ + BETDiskSectionalPolar( + lift_coeffs=[[[0.1, 0.2, 0.3]]], + drag_coeffs=[[[0.01, 0.02, 0.03]]], + ), + BETDiskSectionalPolar( + lift_coeffs=[[[0.15, 0.25, 0.35]]], + drag_coeffs=[[[0.015, 0.025, 0.035]]], + ), + ], + ) + coordinate_system = CoordinateSystem(name="cs", translation=(1, 2, 3) * u.m) + coordinate_system_status = CoordinateSystemStatus( + coordinate_systems=[coordinate_system], + parents=[], + assignments=[ + CoordinateSystemAssignmentGroup( + coordinate_system_id=coordinate_system.private_attribute_id, + entities=[ + CoordinateSystemEntityRef( + entity_type="Cylinder", + entity_id=cylinder.private_attribute_id, + ) + ], + ) + ], + ) + params = SimulationParams( + models=[bet_disk], + private_attribute_asset_cache=AssetCache( + coordinate_system_status=coordinate_system_status, + ), + ) + + apply_coordinate_system_transformations(params) + + transformed_bet_disk = params.models[0] + transformed_cylinder = transformed_bet_disk.entities.stored_entities[0] + + assert all(transformed_cylinder.center == [1, 2, 3] * u.m) + assert transformed_bet_disk.mach_numbers == [0] + assert transformed_bet_disk.twists[0].radius == 0 * u.m + assert transformed_bet_disk.chords[0].chord == 1 * u.m