From 43b0dc3fd86d0c47fa6188696f987f86d55cf233 Mon Sep 17 00:00:00 2001 From: Angran Li Date: Thu, 24 Oct 2024 16:04:49 +0000 Subject: [PATCH 1/6] Hotfix for the boundary_spec_translator --- .../component/simulation/outputs/outputs.py | 10 + .../translator/solver_translator.py | 61 ++++-- .../translator/ref/Flow360_om6Wing.json | 4 + ...om6wing_FS_with_turbulence_quantities.json | 175 ++++++++++++++++++ .../ref/Flow360_om6wing_FS_with_vel.json | 4 + ...low360_om6wing_FS_with_vel_expression.json | 4 + .../translator/test_output_translation.py | 57 +----- .../translator/test_solver_translator.py | 10 + 8 files changed, 264 insertions(+), 61 deletions(-) create mode 100644 tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json diff --git a/flow360/component/simulation/outputs/outputs.py b/flow360/component/simulation/outputs/outputs.py index d6dcb60ae..fc1ef4e7f 100644 --- a/flow360/component/simulation/outputs/outputs.py +++ b/flow360/component/simulation/outputs/outputs.py @@ -134,6 +134,15 @@ class SliceOutput(_AnimationAndFileFormatSettings): output_type: Literal["SliceOutput"] = pd.Field("SliceOutput", frozen=True) +class TimeAverageSliceOutput(SliceOutput): + """TimeAverageSliceOutput output settings.""" + + start_step: Union[pd.NonNegativeInt, Literal[-1]] = pd.Field( + default=-1, description="Physical time step to start calculating averaging" + ) + output_type: Literal["TimeAverageSliceOutput"] = pd.Field("TimeAverageSliceOutput", frozen=True) + + class IsosurfaceOutput(_AnimationAndFileFormatSettings): """Isosurface output settings.""" @@ -214,6 +223,7 @@ class UserDefinedFields(Flow360BaseModel): VolumeOutput, TimeAverageVolumeOutput, SliceOutput, + TimeAverageSliceOutput, IsosurfaceOutput, SurfaceIntegralOutput, ProbeOutput, diff --git a/flow360/component/simulation/translator/solver_translator.py b/flow360/component/simulation/translator/solver_translator.py index cb58440e8..b08a6f0fe 100644 --- a/flow360/component/simulation/translator/solver_translator.py +++ b/flow360/component/simulation/translator/solver_translator.py @@ -1,5 +1,6 @@ """Flow360 solver setting parameter translator.""" +# pylint: disable=too-many-lines from typing import Type, Union from flow360.component.simulation.framework.entity_base import EntityList @@ -41,6 +42,7 @@ SurfaceIntegralOutput, SurfaceOutput, SurfaceProbeOutput, + TimeAverageSliceOutput, TimeAverageSurfaceOutput, TimeAverageVolumeOutput, VolumeOutput, @@ -57,6 +59,7 @@ remove_units_in_dict, replace_dict_key, translate_setting_and_apply_to_all_entities, + update_dict_recursively, ) from flow360.component.simulation.unit_system import LengthType from flow360.exceptions import Flow360TranslationError @@ -74,7 +77,6 @@ def init_non_average_output( has_average_capability: bool, ): """Initialize the common output attribute for non-average output.""" - has_average_capability = class_type.__name__.endswith(("VolumeOutput", "SurfaceOutput")) if has_average_capability: base["computeTimeAverages"] = False @@ -316,17 +318,19 @@ def translate_surface_output( return surface_output -def translate_slice_isosurface_output( +def translate_slice_output( output_params: list, - output_class: Union[SliceOutput, IsosurfaceOutput], - entities_name_key: str, + output_class: Union[SliceOutput, TimeAverageSliceOutput], injection_function, ): """Translate slice or isosurface output settings.""" translated_output = init_output_base( - output_params, output_class, has_average_capability=False, is_average=False + output_params, + output_class, + has_average_capability=True, + is_average=output_class is TimeAverageSliceOutput, ) - translated_output[entities_name_key] = translate_setting_and_apply_to_all_entities( + translated_output["slices"] = translate_setting_and_apply_to_all_entities( output_params, output_class, translation_func=translate_output_fields, @@ -336,6 +340,27 @@ def translate_slice_isosurface_output( return translated_output +def translate_isosurface_output( + output_params: list, + injection_function, +): + """Translate slice or isosurface output settings.""" + translated_output = init_output_base( + output_params, + IsosurfaceOutput, + has_average_capability=False, + is_average=False, + ) + translated_output["isoSurfaces"] = translate_setting_and_apply_to_all_entities( + output_params, + IsosurfaceOutput, + translation_func=translate_output_fields, + to_list=False, + entity_injection_func=injection_function, + ) + return translated_output + + def translate_monitor_output( output_params: list, monitor_type, injection_function, translation_func=translate_output_fields ): @@ -407,20 +432,28 @@ def translate_output(input_params: SimulationParams, translated: dict): outputs, TimeAverageSurfaceOutput, translated ) # Merge - surface_output.update(**surface_output_average) + update_dict_recursively(surface_output, surface_output_average) if surface_output: translated["surfaceOutput"] = add_unused_output_settings_for_comparison(surface_output) ##:: Step3: Get translated["sliceOutput"] + slice_output = {} + slice_output_average = {} if has_instance_in_list(outputs, SliceOutput): - translated["sliceOutput"] = translate_slice_isosurface_output( - outputs, SliceOutput, "slices", inject_slice_info + slice_output = translate_slice_output(outputs, SliceOutput, inject_slice_info) + if has_instance_in_list(outputs, TimeAverageSliceOutput): + slice_output_average = translate_slice_output( + outputs, TimeAverageSliceOutput, inject_slice_info ) + # Merge + update_dict_recursively(slice_output, slice_output_average) + if slice_output: + translated["sliceOutput"] = add_unused_output_settings_for_comparison(slice_output) ##:: Step4: Get translated["isoSurfaceOutput"] if has_instance_in_list(outputs, IsosurfaceOutput): - translated["isoSurfaceOutput"] = translate_slice_isosurface_output( - outputs, IsosurfaceOutput, "isoSurfaces", inject_isosurface_info + translated["isoSurfaceOutput"] = translate_isosurface_output( + outputs, inject_isosurface_info ) ##:: Step5: Get translated["monitorOutput"] @@ -624,6 +657,9 @@ def boundary_spec_translator(model: SurfaceModelTypes, op_acousitc_to_static_pre elif isinstance(model.spec, MassFlowRate): boundary["type"] = "MassInflow" boundary["massFlowRate"] = model_dict["spec"]["value"] + if model.turbulence_quantities is not None: + boundary["turbulenceQuantities"] = model_dict["turbulenceQuantities"] + replace_dict_key(boundary["turbulenceQuantities"], "typeName", "modelType") elif isinstance(model, Outflow): if isinstance(model.spec, Pressure): boundary["type"] = "SubsonicOutflowPressure" @@ -646,6 +682,9 @@ def boundary_spec_translator(model: SurfaceModelTypes, op_acousitc_to_static_pre boundary["type"] = "Freestream" if model.velocity is not None: boundary["velocity"] = list(model_dict["velocity"]) + if model.turbulence_quantities is not None: + boundary["turbulenceQuantities"] = model_dict["turbulenceQuantities"] + replace_dict_key(boundary["turbulenceQuantities"], "typeName", "modelType") elif isinstance(model, SymmetryPlane): boundary["type"] = "SymmetryPlane" diff --git a/tests/simulation/translator/ref/Flow360_om6Wing.json b/tests/simulation/translator/ref/Flow360_om6Wing.json index e9b3df95f..122f30ae7 100644 --- a/tests/simulation/translator/ref/Flow360_om6Wing.json +++ b/tests/simulation/translator/ref/Flow360_om6Wing.json @@ -51,6 +51,10 @@ "sliceOutput": { "animationFrequency": -1, "animationFrequencyOffset": 0, + "animationFrequencyTimeAverage": -1, + "animationFrequencyTimeAverageOffset": 0, + "computeTimeAverages": false, + "startAverageIntegrationStep": -1, "outputFormat": "tecplot", "outputFields": [], "slices": { diff --git a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json new file mode 100644 index 000000000..a4010b8e5 --- /dev/null +++ b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json @@ -0,0 +1,175 @@ +{ + "boundaries": { + "1": { + "type": "NoSlipWall" + }, + "2": { + "type": "SlipWall" + }, + "3": { + "turbulenceQuantities": { + "modelType": "ModifiedTurbulentViscosityRatio", + "modifiedTurbulentViscosityRatio": 10.0 + }, + "type": "Freestream" + } + }, + "freestream": { + "Mach": 0.8399999999999999, + "Temperature": 288.15, + "alphaAngle": 3.06, + "betaAngle": 0.0, + "muRef": 5.326121165140212e-08 + }, + "geometry": { + "momentCenter": [ + 0.0, + 0.0, + 0.0 + ], + "momentLength": [ + 0.801672958512342, + 0.801672958512342, + 0.801672958512342 + ], + "refArea": 1.1529999999999987 + }, + "navierStokesSolver": { + "CFLMultiplier": 1.0, + "absoluteTolerance": 1e-10, + "equationEvalFrequency": 1, + "kappaMUSCL": -1.0, + "limitPressureDensity": false, + "limitVelocity": false, + "linearSolver": { + "maxIterations": 25 + }, + "lowMachPreconditioner": false, + "maxForceJacUpdatePhysicalSteps": 0, + "modelType": "Compressible", + "numericalDissipationFactor": 1.0, + "orderOfAccuracy": 2, + "relativeTolerance": 0.0, + "updateJacobianFrequency": 4 + }, + "sliceOutput": { + "animationFrequency": -1, + "animationFrequencyOffset": 0, + "animationFrequencyTimeAverage": -1, + "animationFrequencyTimeAverageOffset": 0, + "computeTimeAverages": false, + "outputFields": [], + "outputFormat": "tecplot", + "slices": { + "sliceName_1": { + "outputFields": [ + "primitiveVars", + "vorticity", + "T", + "s", + "Cp", + "mut", + "mutRatio", + "Mach" + ], + "sliceNormal": [ + 0.0, + 1.0, + 0.0 + ], + "sliceOrigin": [ + 0.0, + 0.7000000000000001, + 0.0 + ] + } + }, + "startAverageIntegrationStep": -1 + }, + "surfaceOutput": { + "animationFrequency": -1, + "animationFrequencyOffset": 0, + "animationFrequencyTimeAverage": -1, + "animationFrequencyTimeAverageOffset": 0, + "computeTimeAverages": false, + "outputFields": [], + "outputFormat": "paraview", + "startAverageIntegrationStep": -1, + "surfaces": { + "1": { + "outputFields": [ + "nuHat" + ] + }, + "2": { + "outputFields": [ + "nuHat" + ] + }, + "3": { + "outputFields": [ + "nuHat" + ] + } + }, + "writeSingleFile": false + }, + "timeStepping": { + "CFL": { + "final": 200.0, + "initial": 5.0, + "rampSteps": 40, + "type": "ramp" + }, + "maxPseudoSteps": 2000, + "orderOfAccuracy": 2, + "physicalSteps": 1, + "timeStepSize": "inf" + }, + "turbulenceModelSolver": { + "CFLMultiplier": 2.0, + "DDES": false, + "absoluteTolerance": 1e-08, + "equationEvalFrequency": 4, + "gridSizeForLES": "maxEdgeLength", + "linearSolver": { + "maxIterations": 15 + }, + "maxForceJacUpdatePhysicalSteps": 0, + "modelConstants": { + "C_DES": 0.72, + "C_cb1": 0.1355, + "C_cb2": 0.622, + "C_d": 8.0, + "C_min_rd": 10.0, + "C_sigma": 0.6666666666666666, + "C_t3": 1.2, + "C_t4": 0.5, + "C_v1": 7.1, + "C_vonKarman": 0.41, + "C_w2": 0.3 + }, + "modelType": "SpalartAllmaras", + "orderOfAccuracy": 2, + "quadraticConstitutiveRelation": false, + "reconstructionGradientLimiter": 0.5, + "relativeTolerance": 0.0, + "rotationCorrection": false, + "updateJacobianFrequency": 4 + }, + "volumeOutput": { + "animationFrequency": -1, + "animationFrequencyOffset": 0, + "animationFrequencyTimeAverage": -1, + "animationFrequencyTimeAverageOffset": 0, + "computeTimeAverages": false, + "outputFields": [ + "primitiveVars", + "residualNavierStokes", + "residualTurbulence", + "Mach" + ], + "outputFormat": "paraview", + "startAverageIntegrationStep": -1 + } +} \ No newline at end of file diff --git a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel.json b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel.json index 3ca1a4cc3..21cb9d7e2 100644 --- a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel.json +++ b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel.json @@ -56,8 +56,12 @@ "sliceOutput": { "animationFrequency": -1, "animationFrequencyOffset": 0, + "animationFrequencyTimeAverage": -1, + "animationFrequencyTimeAverageOffset": 0, + "computeTimeAverages": false, "outputFormat": "tecplot", "outputFields": [], + "startAverageIntegrationStep": -1, "slices": { "sliceName_1": { "outputFields": [ diff --git a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel_expression.json b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel_expression.json index 007b04bd3..9007f06ae 100644 --- a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel_expression.json +++ b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel_expression.json @@ -56,8 +56,12 @@ "sliceOutput": { "animationFrequency": -1, "animationFrequencyOffset": 0, + "animationFrequencyTimeAverage": -1, + "animationFrequencyTimeAverageOffset": 0, + "computeTimeAverages": false, "outputFormat": "tecplot", "outputFields": [], + "startAverageIntegrationStep": -1, "slices": { "sliceName_1": { "outputFields": [ diff --git a/tests/simulation/translator/test_output_translation.py b/tests/simulation/translator/test_output_translation.py index 93fd120e2..ec4bafd63 100644 --- a/tests/simulation/translator/test_output_translation.py +++ b/tests/simulation/translator/test_output_translation.py @@ -106,54 +106,6 @@ def test_volume_output(volume_output_config, avg_volume_output_config): assert sorted(ref["volumeOutput"].items()) == sorted(translated["volumeOutput"].items()) -@pytest.fixture() -def surface_output_config(): - return ( - [ - SurfaceOutput( # Global - frequency=11, - frequency_offset=21, - output_format="paraview", - output_fields=["vorticity", "mutRatio"], - ), - SurfaceOutput( # Local - frequency=11, - frequency_offset=21, - entities=[Surface(name="surface1"), Surface(name="surface2")], - output_fields=["Cp"], - ), - SurfaceOutput( # Local - frequency=11, - frequency_offset=21, - entities=[ - Surface(name="surface11", private_attribute_full_name="ZoneName/surface11"), - Surface(name="surface22"), - ], - output_fields=["T"], - ), - ], - { - "animationFrequency": 11, - "animationFrequencyOffset": 21, - "animationFrequencyTimeAverage": -1, - "animationFrequencyTimeAverageOffset": 0, - "computeTimeAverages": False, - "outputFields": [], - "outputFormat": "paraview", - "startAverageIntegrationStep": -1, - "surfaces": { - "surface1": {"outputFields": ["Cp", "vorticity", "mutRatio"]}, - "ZoneName/surface11": {"outputFields": ["T", "vorticity", "mutRatio"]}, - "surface2": {"outputFields": ["Cp", "vorticity", "mutRatio"]}, - "surface22": {"outputFields": ["T", "vorticity", "mutRatio"]}, - "Wall1": {"outputFields": ["vorticity", "mutRatio"]}, - "Wall2": {"outputFields": ["vorticity", "mutRatio"]}, - }, - "writeSingleFile": False, - }, - ) - - @pytest.fixture() def surface_output_config(): return ( @@ -201,13 +153,13 @@ def avg_surface_output_config(): output_fields=["Cp"], ), TimeAverageSurfaceOutput( # Local - entities=[Surface(name="surface11"), Surface(name="surface22")], + entities=[Surface(name="surface3")], output_fields=["T"], ), ] -def test_surface_ouput( +def test_surface_output( surface_output_config, avg_surface_output_config, ): @@ -237,6 +189,7 @@ def test_surface_ouput( "surface11": {"outputFields": ["T"]}, "surface2": {"outputFields": ["Cp"]}, "surface22": {"outputFields": ["T"]}, + "surface3": {"outputFields": ["T"]}, }, "writeSingleFile": False, } @@ -287,6 +240,10 @@ def sliceoutput_config(): { "animationFrequency": 33, "animationFrequencyOffset": 22, + "animationFrequencyTimeAverage": -1, + "animationFrequencyTimeAverageOffset": 0, + "startAverageIntegrationStep": -1, + "computeTimeAverages": False, "outputFields": [], "outputFormat": "tecplot", "slices": { diff --git a/tests/simulation/translator/test_solver_translator.py b/tests/simulation/translator/test_solver_translator.py index b3cc42ad9..890ea99b9 100644 --- a/tests/simulation/translator/test_solver_translator.py +++ b/tests/simulation/translator/test_solver_translator.py @@ -14,6 +14,9 @@ SlipWall, Wall, ) +from flow360.component.simulation.models.turbulence_quantities import ( + TurbulenceQuantities, +) from flow360.component.simulation.models.volume_models import Fluid from flow360.component.simulation.operating_condition.operating_condition import ( AerospaceCondition, @@ -171,6 +174,13 @@ def test_om6wing_tutorial(get_om6Wing_tutorial_param): def test_om6wing_with_specified_freestream_BC(get_om6Wing_tutorial_param): params = get_om6Wing_tutorial_param + params.models[3].turbulence_quantities = TurbulenceQuantities(modified_viscosity_ratio=10) + translate_and_compare( + get_om6Wing_tutorial_param, + mesh_unit=0.8059 * u.m, + ref_json_file="Flow360_om6wing_FS_with_turbulence_quantities.json", + ) + params.models[3].turbulence_quantities = None params.models[3].velocity = (01.0, 10.0, 0.0) * u.m / u.s translate_and_compare( get_om6Wing_tutorial_param, From 9d573c034c94a058884e2b25e1dc1e67216da063 Mon Sep 17 00:00:00 2001 From: Angran Li Date: Thu, 24 Oct 2024 18:29:22 +0000 Subject: [PATCH 2/6] Revert merged change --- .../component/simulation/outputs/outputs.py | 10 - .../translator/solver_translator.py | 61 ++---- .../translator/ref/Flow360_om6Wing.json | 4 - ...om6wing_FS_with_turbulence_quantities.json | 175 ------------------ .../ref/Flow360_om6wing_FS_with_vel.json | 4 - ...low360_om6wing_FS_with_vel_expression.json | 4 - .../translator/test_output_translation.py | 57 +++++- .../translator/test_solver_translator.py | 10 - 8 files changed, 61 insertions(+), 264 deletions(-) delete mode 100644 tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json diff --git a/flow360/component/simulation/outputs/outputs.py b/flow360/component/simulation/outputs/outputs.py index fc1ef4e7f..d6dcb60ae 100644 --- a/flow360/component/simulation/outputs/outputs.py +++ b/flow360/component/simulation/outputs/outputs.py @@ -134,15 +134,6 @@ class SliceOutput(_AnimationAndFileFormatSettings): output_type: Literal["SliceOutput"] = pd.Field("SliceOutput", frozen=True) -class TimeAverageSliceOutput(SliceOutput): - """TimeAverageSliceOutput output settings.""" - - start_step: Union[pd.NonNegativeInt, Literal[-1]] = pd.Field( - default=-1, description="Physical time step to start calculating averaging" - ) - output_type: Literal["TimeAverageSliceOutput"] = pd.Field("TimeAverageSliceOutput", frozen=True) - - class IsosurfaceOutput(_AnimationAndFileFormatSettings): """Isosurface output settings.""" @@ -223,7 +214,6 @@ class UserDefinedFields(Flow360BaseModel): VolumeOutput, TimeAverageVolumeOutput, SliceOutput, - TimeAverageSliceOutput, IsosurfaceOutput, SurfaceIntegralOutput, ProbeOutput, diff --git a/flow360/component/simulation/translator/solver_translator.py b/flow360/component/simulation/translator/solver_translator.py index b08a6f0fe..cb58440e8 100644 --- a/flow360/component/simulation/translator/solver_translator.py +++ b/flow360/component/simulation/translator/solver_translator.py @@ -1,6 +1,5 @@ """Flow360 solver setting parameter translator.""" -# pylint: disable=too-many-lines from typing import Type, Union from flow360.component.simulation.framework.entity_base import EntityList @@ -42,7 +41,6 @@ SurfaceIntegralOutput, SurfaceOutput, SurfaceProbeOutput, - TimeAverageSliceOutput, TimeAverageSurfaceOutput, TimeAverageVolumeOutput, VolumeOutput, @@ -59,7 +57,6 @@ remove_units_in_dict, replace_dict_key, translate_setting_and_apply_to_all_entities, - update_dict_recursively, ) from flow360.component.simulation.unit_system import LengthType from flow360.exceptions import Flow360TranslationError @@ -77,6 +74,7 @@ def init_non_average_output( has_average_capability: bool, ): """Initialize the common output attribute for non-average output.""" + has_average_capability = class_type.__name__.endswith(("VolumeOutput", "SurfaceOutput")) if has_average_capability: base["computeTimeAverages"] = False @@ -318,19 +316,17 @@ def translate_surface_output( return surface_output -def translate_slice_output( +def translate_slice_isosurface_output( output_params: list, - output_class: Union[SliceOutput, TimeAverageSliceOutput], + output_class: Union[SliceOutput, IsosurfaceOutput], + entities_name_key: str, injection_function, ): """Translate slice or isosurface output settings.""" translated_output = init_output_base( - output_params, - output_class, - has_average_capability=True, - is_average=output_class is TimeAverageSliceOutput, + output_params, output_class, has_average_capability=False, is_average=False ) - translated_output["slices"] = translate_setting_and_apply_to_all_entities( + translated_output[entities_name_key] = translate_setting_and_apply_to_all_entities( output_params, output_class, translation_func=translate_output_fields, @@ -340,27 +336,6 @@ def translate_slice_output( return translated_output -def translate_isosurface_output( - output_params: list, - injection_function, -): - """Translate slice or isosurface output settings.""" - translated_output = init_output_base( - output_params, - IsosurfaceOutput, - has_average_capability=False, - is_average=False, - ) - translated_output["isoSurfaces"] = translate_setting_and_apply_to_all_entities( - output_params, - IsosurfaceOutput, - translation_func=translate_output_fields, - to_list=False, - entity_injection_func=injection_function, - ) - return translated_output - - def translate_monitor_output( output_params: list, monitor_type, injection_function, translation_func=translate_output_fields ): @@ -432,28 +407,20 @@ def translate_output(input_params: SimulationParams, translated: dict): outputs, TimeAverageSurfaceOutput, translated ) # Merge - update_dict_recursively(surface_output, surface_output_average) + surface_output.update(**surface_output_average) if surface_output: translated["surfaceOutput"] = add_unused_output_settings_for_comparison(surface_output) ##:: Step3: Get translated["sliceOutput"] - slice_output = {} - slice_output_average = {} if has_instance_in_list(outputs, SliceOutput): - slice_output = translate_slice_output(outputs, SliceOutput, inject_slice_info) - if has_instance_in_list(outputs, TimeAverageSliceOutput): - slice_output_average = translate_slice_output( - outputs, TimeAverageSliceOutput, inject_slice_info + translated["sliceOutput"] = translate_slice_isosurface_output( + outputs, SliceOutput, "slices", inject_slice_info ) - # Merge - update_dict_recursively(slice_output, slice_output_average) - if slice_output: - translated["sliceOutput"] = add_unused_output_settings_for_comparison(slice_output) ##:: Step4: Get translated["isoSurfaceOutput"] if has_instance_in_list(outputs, IsosurfaceOutput): - translated["isoSurfaceOutput"] = translate_isosurface_output( - outputs, inject_isosurface_info + translated["isoSurfaceOutput"] = translate_slice_isosurface_output( + outputs, IsosurfaceOutput, "isoSurfaces", inject_isosurface_info ) ##:: Step5: Get translated["monitorOutput"] @@ -657,9 +624,6 @@ def boundary_spec_translator(model: SurfaceModelTypes, op_acousitc_to_static_pre elif isinstance(model.spec, MassFlowRate): boundary["type"] = "MassInflow" boundary["massFlowRate"] = model_dict["spec"]["value"] - if model.turbulence_quantities is not None: - boundary["turbulenceQuantities"] = model_dict["turbulenceQuantities"] - replace_dict_key(boundary["turbulenceQuantities"], "typeName", "modelType") elif isinstance(model, Outflow): if isinstance(model.spec, Pressure): boundary["type"] = "SubsonicOutflowPressure" @@ -682,9 +646,6 @@ def boundary_spec_translator(model: SurfaceModelTypes, op_acousitc_to_static_pre boundary["type"] = "Freestream" if model.velocity is not None: boundary["velocity"] = list(model_dict["velocity"]) - if model.turbulence_quantities is not None: - boundary["turbulenceQuantities"] = model_dict["turbulenceQuantities"] - replace_dict_key(boundary["turbulenceQuantities"], "typeName", "modelType") elif isinstance(model, SymmetryPlane): boundary["type"] = "SymmetryPlane" diff --git a/tests/simulation/translator/ref/Flow360_om6Wing.json b/tests/simulation/translator/ref/Flow360_om6Wing.json index 122f30ae7..e9b3df95f 100644 --- a/tests/simulation/translator/ref/Flow360_om6Wing.json +++ b/tests/simulation/translator/ref/Flow360_om6Wing.json @@ -51,10 +51,6 @@ "sliceOutput": { "animationFrequency": -1, "animationFrequencyOffset": 0, - "animationFrequencyTimeAverage": -1, - "animationFrequencyTimeAverageOffset": 0, - "computeTimeAverages": false, - "startAverageIntegrationStep": -1, "outputFormat": "tecplot", "outputFields": [], "slices": { diff --git a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json deleted file mode 100644 index a4010b8e5..000000000 --- a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json +++ /dev/null @@ -1,175 +0,0 @@ -{ - "boundaries": { - "1": { - "type": "NoSlipWall" - }, - "2": { - "type": "SlipWall" - }, - "3": { - "turbulenceQuantities": { - "modelType": "ModifiedTurbulentViscosityRatio", - "modifiedTurbulentViscosityRatio": 10.0 - }, - "type": "Freestream" - } - }, - "freestream": { - "Mach": 0.8399999999999999, - "Temperature": 288.15, - "alphaAngle": 3.06, - "betaAngle": 0.0, - "muRef": 5.326121165140212e-08 - }, - "geometry": { - "momentCenter": [ - 0.0, - 0.0, - 0.0 - ], - "momentLength": [ - 0.801672958512342, - 0.801672958512342, - 0.801672958512342 - ], - "refArea": 1.1529999999999987 - }, - "navierStokesSolver": { - "CFLMultiplier": 1.0, - "absoluteTolerance": 1e-10, - "equationEvalFrequency": 1, - "kappaMUSCL": -1.0, - "limitPressureDensity": false, - "limitVelocity": false, - "linearSolver": { - "maxIterations": 25 - }, - "lowMachPreconditioner": false, - "maxForceJacUpdatePhysicalSteps": 0, - "modelType": "Compressible", - "numericalDissipationFactor": 1.0, - "orderOfAccuracy": 2, - "relativeTolerance": 0.0, - "updateJacobianFrequency": 4 - }, - "sliceOutput": { - "animationFrequency": -1, - "animationFrequencyOffset": 0, - "animationFrequencyTimeAverage": -1, - "animationFrequencyTimeAverageOffset": 0, - "computeTimeAverages": false, - "outputFields": [], - "outputFormat": "tecplot", - "slices": { - "sliceName_1": { - "outputFields": [ - "primitiveVars", - "vorticity", - "T", - "s", - "Cp", - "mut", - "mutRatio", - "Mach" - ], - "sliceNormal": [ - 0.0, - 1.0, - 0.0 - ], - "sliceOrigin": [ - 0.0, - 0.7000000000000001, - 0.0 - ] - } - }, - "startAverageIntegrationStep": -1 - }, - "surfaceOutput": { - "animationFrequency": -1, - "animationFrequencyOffset": 0, - "animationFrequencyTimeAverage": -1, - "animationFrequencyTimeAverageOffset": 0, - "computeTimeAverages": false, - "outputFields": [], - "outputFormat": "paraview", - "startAverageIntegrationStep": -1, - "surfaces": { - "1": { - "outputFields": [ - "nuHat" - ] - }, - "2": { - "outputFields": [ - "nuHat" - ] - }, - "3": { - "outputFields": [ - "nuHat" - ] - } - }, - "writeSingleFile": false - }, - "timeStepping": { - "CFL": { - "final": 200.0, - "initial": 5.0, - "rampSteps": 40, - "type": "ramp" - }, - "maxPseudoSteps": 2000, - "orderOfAccuracy": 2, - "physicalSteps": 1, - "timeStepSize": "inf" - }, - "turbulenceModelSolver": { - "CFLMultiplier": 2.0, - "DDES": false, - "absoluteTolerance": 1e-08, - "equationEvalFrequency": 4, - "gridSizeForLES": "maxEdgeLength", - "linearSolver": { - "maxIterations": 15 - }, - "maxForceJacUpdatePhysicalSteps": 0, - "modelConstants": { - "C_DES": 0.72, - "C_cb1": 0.1355, - "C_cb2": 0.622, - "C_d": 8.0, - "C_min_rd": 10.0, - "C_sigma": 0.6666666666666666, - "C_t3": 1.2, - "C_t4": 0.5, - "C_v1": 7.1, - "C_vonKarman": 0.41, - "C_w2": 0.3 - }, - "modelType": "SpalartAllmaras", - "orderOfAccuracy": 2, - "quadraticConstitutiveRelation": false, - "reconstructionGradientLimiter": 0.5, - "relativeTolerance": 0.0, - "rotationCorrection": false, - "updateJacobianFrequency": 4 - }, - "volumeOutput": { - "animationFrequency": -1, - "animationFrequencyOffset": 0, - "animationFrequencyTimeAverage": -1, - "animationFrequencyTimeAverageOffset": 0, - "computeTimeAverages": false, - "outputFields": [ - "primitiveVars", - "residualNavierStokes", - "residualTurbulence", - "Mach" - ], - "outputFormat": "paraview", - "startAverageIntegrationStep": -1 - } -} \ No newline at end of file diff --git a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel.json b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel.json index 21cb9d7e2..3ca1a4cc3 100644 --- a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel.json +++ b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel.json @@ -56,12 +56,8 @@ "sliceOutput": { "animationFrequency": -1, "animationFrequencyOffset": 0, - "animationFrequencyTimeAverage": -1, - "animationFrequencyTimeAverageOffset": 0, - "computeTimeAverages": false, "outputFormat": "tecplot", "outputFields": [], - "startAverageIntegrationStep": -1, "slices": { "sliceName_1": { "outputFields": [ diff --git a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel_expression.json b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel_expression.json index 9007f06ae..007b04bd3 100644 --- a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel_expression.json +++ b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_vel_expression.json @@ -56,12 +56,8 @@ "sliceOutput": { "animationFrequency": -1, "animationFrequencyOffset": 0, - "animationFrequencyTimeAverage": -1, - "animationFrequencyTimeAverageOffset": 0, - "computeTimeAverages": false, "outputFormat": "tecplot", "outputFields": [], - "startAverageIntegrationStep": -1, "slices": { "sliceName_1": { "outputFields": [ diff --git a/tests/simulation/translator/test_output_translation.py b/tests/simulation/translator/test_output_translation.py index ec4bafd63..93fd120e2 100644 --- a/tests/simulation/translator/test_output_translation.py +++ b/tests/simulation/translator/test_output_translation.py @@ -106,6 +106,54 @@ def test_volume_output(volume_output_config, avg_volume_output_config): assert sorted(ref["volumeOutput"].items()) == sorted(translated["volumeOutput"].items()) +@pytest.fixture() +def surface_output_config(): + return ( + [ + SurfaceOutput( # Global + frequency=11, + frequency_offset=21, + output_format="paraview", + output_fields=["vorticity", "mutRatio"], + ), + SurfaceOutput( # Local + frequency=11, + frequency_offset=21, + entities=[Surface(name="surface1"), Surface(name="surface2")], + output_fields=["Cp"], + ), + SurfaceOutput( # Local + frequency=11, + frequency_offset=21, + entities=[ + Surface(name="surface11", private_attribute_full_name="ZoneName/surface11"), + Surface(name="surface22"), + ], + output_fields=["T"], + ), + ], + { + "animationFrequency": 11, + "animationFrequencyOffset": 21, + "animationFrequencyTimeAverage": -1, + "animationFrequencyTimeAverageOffset": 0, + "computeTimeAverages": False, + "outputFields": [], + "outputFormat": "paraview", + "startAverageIntegrationStep": -1, + "surfaces": { + "surface1": {"outputFields": ["Cp", "vorticity", "mutRatio"]}, + "ZoneName/surface11": {"outputFields": ["T", "vorticity", "mutRatio"]}, + "surface2": {"outputFields": ["Cp", "vorticity", "mutRatio"]}, + "surface22": {"outputFields": ["T", "vorticity", "mutRatio"]}, + "Wall1": {"outputFields": ["vorticity", "mutRatio"]}, + "Wall2": {"outputFields": ["vorticity", "mutRatio"]}, + }, + "writeSingleFile": False, + }, + ) + + @pytest.fixture() def surface_output_config(): return ( @@ -153,13 +201,13 @@ def avg_surface_output_config(): output_fields=["Cp"], ), TimeAverageSurfaceOutput( # Local - entities=[Surface(name="surface3")], + entities=[Surface(name="surface11"), Surface(name="surface22")], output_fields=["T"], ), ] -def test_surface_output( +def test_surface_ouput( surface_output_config, avg_surface_output_config, ): @@ -189,7 +237,6 @@ def test_surface_output( "surface11": {"outputFields": ["T"]}, "surface2": {"outputFields": ["Cp"]}, "surface22": {"outputFields": ["T"]}, - "surface3": {"outputFields": ["T"]}, }, "writeSingleFile": False, } @@ -240,10 +287,6 @@ def sliceoutput_config(): { "animationFrequency": 33, "animationFrequencyOffset": 22, - "animationFrequencyTimeAverage": -1, - "animationFrequencyTimeAverageOffset": 0, - "startAverageIntegrationStep": -1, - "computeTimeAverages": False, "outputFields": [], "outputFormat": "tecplot", "slices": { diff --git a/tests/simulation/translator/test_solver_translator.py b/tests/simulation/translator/test_solver_translator.py index 890ea99b9..b3cc42ad9 100644 --- a/tests/simulation/translator/test_solver_translator.py +++ b/tests/simulation/translator/test_solver_translator.py @@ -14,9 +14,6 @@ SlipWall, Wall, ) -from flow360.component.simulation.models.turbulence_quantities import ( - TurbulenceQuantities, -) from flow360.component.simulation.models.volume_models import Fluid from flow360.component.simulation.operating_condition.operating_condition import ( AerospaceCondition, @@ -174,13 +171,6 @@ def test_om6wing_tutorial(get_om6Wing_tutorial_param): def test_om6wing_with_specified_freestream_BC(get_om6Wing_tutorial_param): params = get_om6Wing_tutorial_param - params.models[3].turbulence_quantities = TurbulenceQuantities(modified_viscosity_ratio=10) - translate_and_compare( - get_om6Wing_tutorial_param, - mesh_unit=0.8059 * u.m, - ref_json_file="Flow360_om6wing_FS_with_turbulence_quantities.json", - ) - params.models[3].turbulence_quantities = None params.models[3].velocity = (01.0, 10.0, 0.0) * u.m / u.s translate_and_compare( get_om6Wing_tutorial_param, From 3e72816bbc6b7fc133b75b78634c47da3f764b60 Mon Sep 17 00:00:00 2001 From: Angran Li Date: Wed, 23 Oct 2024 16:18:10 +0000 Subject: [PATCH 3/6] fix boundary spec translator --- flow360/component/simulation/translator/solver_translator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flow360/component/simulation/translator/solver_translator.py b/flow360/component/simulation/translator/solver_translator.py index cb58440e8..153b4cceb 100644 --- a/flow360/component/simulation/translator/solver_translator.py +++ b/flow360/component/simulation/translator/solver_translator.py @@ -646,6 +646,9 @@ def boundary_spec_translator(model: SurfaceModelTypes, op_acousitc_to_static_pre boundary["type"] = "Freestream" if model.velocity is not None: boundary["velocity"] = list(model_dict["velocity"]) + if model.turbulence_quantities is not None: + boundary["turbulenceQuantities"] = model_dict["turbulenceQuantities"] + replace_dict_key(boundary["turbulenceQuantities"], "typeName", "modelType") elif isinstance(model, SymmetryPlane): boundary["type"] = "SymmetryPlane" From 37a56bec0333f79a4553880c322748c5a69a9cc3 Mon Sep 17 00:00:00 2001 From: Angran Li Date: Thu, 24 Oct 2024 13:25:28 +0000 Subject: [PATCH 4/6] More fix on the boundary_spec_translator --- flow360/component/simulation/translator/solver_translator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/flow360/component/simulation/translator/solver_translator.py b/flow360/component/simulation/translator/solver_translator.py index 153b4cceb..fd95a1233 100644 --- a/flow360/component/simulation/translator/solver_translator.py +++ b/flow360/component/simulation/translator/solver_translator.py @@ -624,6 +624,9 @@ def boundary_spec_translator(model: SurfaceModelTypes, op_acousitc_to_static_pre elif isinstance(model.spec, MassFlowRate): boundary["type"] = "MassInflow" boundary["massFlowRate"] = model_dict["spec"]["value"] + if model.turbulence_quantities is not None: + boundary["turbulenceQuantities"] = model_dict["turbulenceQuantities"] + replace_dict_key(boundary["turbulenceQuantities"], "typeName", "modelType") elif isinstance(model, Outflow): if isinstance(model.spec, Pressure): boundary["type"] = "SubsonicOutflowPressure" From 398d5897118e904995b9627fd1ed49532fc1c1ab Mon Sep 17 00:00:00 2001 From: Angran Li Date: Thu, 24 Oct 2024 13:32:06 +0000 Subject: [PATCH 5/6] Fix pylint --- flow360/component/simulation/translator/solver_translator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/flow360/component/simulation/translator/solver_translator.py b/flow360/component/simulation/translator/solver_translator.py index fd95a1233..268ad6984 100644 --- a/flow360/component/simulation/translator/solver_translator.py +++ b/flow360/component/simulation/translator/solver_translator.py @@ -1,5 +1,6 @@ """Flow360 solver setting parameter translator.""" +# pylint: disable=too-many-lines from typing import Type, Union from flow360.component.simulation.framework.entity_base import EntityList From e69064b40083780644b1c510b1d31376ef44957c Mon Sep 17 00:00:00 2001 From: Angran Li Date: Thu, 24 Oct 2024 14:01:15 +0000 Subject: [PATCH 6/6] Add unit test --- ...om6wing_FS_with_turbulence_quantities.json | 175 ++++++++++++++++++ .../translator/test_solver_translator.py | 10 + 2 files changed, 185 insertions(+) create mode 100644 tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json diff --git a/tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json new file mode 100644 index 000000000..a4010b8e5 --- /dev/null +++ b/tests/simulation/translator/ref/Flow360_om6wing_FS_with_turbulence_quantities.json @@ -0,0 +1,175 @@ +{ + "boundaries": { + "1": { + "type": "NoSlipWall" + }, + "2": { + "type": "SlipWall" + }, + "3": { + "turbulenceQuantities": { + "modelType": "ModifiedTurbulentViscosityRatio", + "modifiedTurbulentViscosityRatio": 10.0 + }, + "type": "Freestream" + } + }, + "freestream": { + "Mach": 0.8399999999999999, + "Temperature": 288.15, + "alphaAngle": 3.06, + "betaAngle": 0.0, + "muRef": 5.326121165140212e-08 + }, + "geometry": { + "momentCenter": [ + 0.0, + 0.0, + 0.0 + ], + "momentLength": [ + 0.801672958512342, + 0.801672958512342, + 0.801672958512342 + ], + "refArea": 1.1529999999999987 + }, + "navierStokesSolver": { + "CFLMultiplier": 1.0, + "absoluteTolerance": 1e-10, + "equationEvalFrequency": 1, + "kappaMUSCL": -1.0, + "limitPressureDensity": false, + "limitVelocity": false, + "linearSolver": { + "maxIterations": 25 + }, + "lowMachPreconditioner": false, + "maxForceJacUpdatePhysicalSteps": 0, + "modelType": "Compressible", + "numericalDissipationFactor": 1.0, + "orderOfAccuracy": 2, + "relativeTolerance": 0.0, + "updateJacobianFrequency": 4 + }, + "sliceOutput": { + "animationFrequency": -1, + "animationFrequencyOffset": 0, + "animationFrequencyTimeAverage": -1, + "animationFrequencyTimeAverageOffset": 0, + "computeTimeAverages": false, + "outputFields": [], + "outputFormat": "tecplot", + "slices": { + "sliceName_1": { + "outputFields": [ + "primitiveVars", + "vorticity", + "T", + "s", + "Cp", + "mut", + "mutRatio", + "Mach" + ], + "sliceNormal": [ + 0.0, + 1.0, + 0.0 + ], + "sliceOrigin": [ + 0.0, + 0.7000000000000001, + 0.0 + ] + } + }, + "startAverageIntegrationStep": -1 + }, + "surfaceOutput": { + "animationFrequency": -1, + "animationFrequencyOffset": 0, + "animationFrequencyTimeAverage": -1, + "animationFrequencyTimeAverageOffset": 0, + "computeTimeAverages": false, + "outputFields": [], + "outputFormat": "paraview", + "startAverageIntegrationStep": -1, + "surfaces": { + "1": { + "outputFields": [ + "nuHat" + ] + }, + "2": { + "outputFields": [ + "nuHat" + ] + }, + "3": { + "outputFields": [ + "nuHat" + ] + } + }, + "writeSingleFile": false + }, + "timeStepping": { + "CFL": { + "final": 200.0, + "initial": 5.0, + "rampSteps": 40, + "type": "ramp" + }, + "maxPseudoSteps": 2000, + "orderOfAccuracy": 2, + "physicalSteps": 1, + "timeStepSize": "inf" + }, + "turbulenceModelSolver": { + "CFLMultiplier": 2.0, + "DDES": false, + "absoluteTolerance": 1e-08, + "equationEvalFrequency": 4, + "gridSizeForLES": "maxEdgeLength", + "linearSolver": { + "maxIterations": 15 + }, + "maxForceJacUpdatePhysicalSteps": 0, + "modelConstants": { + "C_DES": 0.72, + "C_cb1": 0.1355, + "C_cb2": 0.622, + "C_d": 8.0, + "C_min_rd": 10.0, + "C_sigma": 0.6666666666666666, + "C_t3": 1.2, + "C_t4": 0.5, + "C_v1": 7.1, + "C_vonKarman": 0.41, + "C_w2": 0.3 + }, + "modelType": "SpalartAllmaras", + "orderOfAccuracy": 2, + "quadraticConstitutiveRelation": false, + "reconstructionGradientLimiter": 0.5, + "relativeTolerance": 0.0, + "rotationCorrection": false, + "updateJacobianFrequency": 4 + }, + "volumeOutput": { + "animationFrequency": -1, + "animationFrequencyOffset": 0, + "animationFrequencyTimeAverage": -1, + "animationFrequencyTimeAverageOffset": 0, + "computeTimeAverages": false, + "outputFields": [ + "primitiveVars", + "residualNavierStokes", + "residualTurbulence", + "Mach" + ], + "outputFormat": "paraview", + "startAverageIntegrationStep": -1 + } +} \ No newline at end of file diff --git a/tests/simulation/translator/test_solver_translator.py b/tests/simulation/translator/test_solver_translator.py index b3cc42ad9..890ea99b9 100644 --- a/tests/simulation/translator/test_solver_translator.py +++ b/tests/simulation/translator/test_solver_translator.py @@ -14,6 +14,9 @@ SlipWall, Wall, ) +from flow360.component.simulation.models.turbulence_quantities import ( + TurbulenceQuantities, +) from flow360.component.simulation.models.volume_models import Fluid from flow360.component.simulation.operating_condition.operating_condition import ( AerospaceCondition, @@ -171,6 +174,13 @@ def test_om6wing_tutorial(get_om6Wing_tutorial_param): def test_om6wing_with_specified_freestream_BC(get_om6Wing_tutorial_param): params = get_om6Wing_tutorial_param + params.models[3].turbulence_quantities = TurbulenceQuantities(modified_viscosity_ratio=10) + translate_and_compare( + get_om6Wing_tutorial_param, + mesh_unit=0.8059 * u.m, + ref_json_file="Flow360_om6wing_FS_with_turbulence_quantities.json", + ) + params.models[3].turbulence_quantities = None params.models[3].velocity = (01.0, 10.0, 0.0) * u.m / u.s translate_and_compare( get_om6Wing_tutorial_param,