From bd856b97bdd79e439743b3014c6f2535c96fdfde Mon Sep 17 00:00:00 2001 From: Oleg Chernukhin Date: Thu, 7 Nov 2024 15:48:08 -0500 Subject: [PATCH 1/7] feat: use settings apis for system coupling --- src/ansys/fluent/core/systemcoupling.py | 108 ++++++++++++++++++++++-- tests/test_systemcoupling.py | 17 +++- 2 files changed, 114 insertions(+), 11 deletions(-) diff --git a/src/ansys/fluent/core/systemcoupling.py b/src/ansys/fluent/core/systemcoupling.py index 945cfdc2c8b..83da47ecbfc 100644 --- a/src/ansys/fluent/core/systemcoupling.py +++ b/src/ansys/fluent/core/systemcoupling.py @@ -53,6 +53,9 @@ def __init__(self, solver): raise RuntimeError( f"Using {str(self._solver.get_fluent_version())}. PySystemCoupling integration requires {str(FluentVersion.v241)} or later." ) + if self._solver.get_fluent_version() >= FluentVersion.v251: + # enable feature to be able to make System Coupling settings APIs calls + self._solver.scheme_eval.scheme_eval("(enable-feature 'sc/participant-info)") @property def participant_type(self) -> str: @@ -61,32 +64,123 @@ def participant_type(self) -> str: def get_variables(self) -> List[Variable]: """Get variables.""" - return self.__get_syc_setup()["variables"] + + if self._solver.get_fluent_version() >= FluentVersion.v251: + variables = list() + region_names = self._solver.settings.setup.models.system_coupling.get_all_regions() + variable_names = set() + for region_name in region_names: + in_var_names = self._get_list(self._solver.settings.setup.models.system_coupling.get_input_vars(region_name=region_name)) + out_var_names = self._get_list(self._solver.settings.setup.models.system_coupling.get_output_vars(region_name=region_name)) + variable_names.update(in_var_names) + variable_names.update(out_var_names) + variable_names = sorted(list(variable_names)) + for variable_name in variable_names: + variables.append( + Variable( + name=variable_name, + display_name=self._get_display_name(variable_name), + tensor_type=self._solver.settings.setup.models.system_coupling.get_tensor_type(variable_name=variable_name), + is_extensive=self._solver.settings.setup.models.system_coupling.is_extensive_var(variable_name=variable_name), + location=self._solver.settings.setup.models.system_coupling.get_data_location(variable_name=variable_name), + quantity_type=self._get_quantity_type(variable_name), + ) + ) + return variables + else: + # maintains back-compatibility for 24.1 and 24.2 + return self.__get_syc_setup()["variables"] def get_regions(self) -> List[Region]: """Get regions.""" - return self.__get_syc_setup()["regions"] + + if self._solver.get_fluent_version() >= FluentVersion.v251: + region_names = self._solver.settings.setup.models.system_coupling.get_all_regions() + regions = list() + for region_name in region_names: + regions.append( + Region( + name=region_name, + display_name=self._get_display_name(region_name), + topology=self._solver.settings.setup.models.system_coupling.get_topology(region_name=region_name), + input_variables=self._get_list(self._solver.settings.setup.models.system_coupling.get_input_vars(region_name=region_name)), + output_variables=self._get_list(self._solver.settings.setup.models.system_coupling.get_output_vars(region_name=region_name)), + ) + ) + return regions + else: + # maintains back-compatibility for 24.1 and 24.2 + return self.__get_syc_setup()["regions"] def get_analysis_type(self) -> str: """Get analysis type.""" - return self.__get_syc_setup()["analysis-type"] + if self._solver.get_fluent_version() >= FluentVersion.v251: + return self._solver.settings.setup.models.system_coupling.get_analysis_type() + else: + # maintains back-compatibility for 24.1 and 24.2 + return self.__get_syc_setup()["analysis-type"] def connect(self, host: str, port: int, name: str) -> None: - """Connect parallelly.""" - self._solver.setup.models.system_coupling.connect_parallel( + """Connect to System Coupling.""" + self._solver.settings.setup.models.system_coupling.connect_parallel( schost=host, scport=port, scname=name ) def solve(self) -> None: """Initialize and solve.""" - self._solver.setup.models.system_coupling.init_and_solve() + self._solver.settings.setup.models.system_coupling.init_and_solve() + + @staticmethod + def _get_quantity_type(variable_name: str) -> str: + """ + For some variables, System Coupling should know the quantity type. + """ + if variable_name in {"force", "lorentz-force"}: + return "Force" + elif variable_name in {"heatflow", "heatrate"}: + return "Heat Rate" + elif variable_name == "displacement": + return "Incremental Displacement" + elif variable_name == "temperature": + return "Temperature" + elif variable_name == "heat-transfer-coefficient": + return "Heat Transfer Coefficient" + elif variable_name == "near-wall-temperature": + return "Convection Reference Temperature" + elif variable_name == "electrical-conductivity": + return "Electrical Conductivity" + else: + return "Unspecified" + + @staticmethod + def _get_display_name(internal_name: str) -> str: + """ + Display names should not contain dashes. + """ + return internal_name.replace("-", " ") + + @staticmethod + def _get_list(value: list | None) -> list: + if isinstance(value, list): + return value + elif value == None: + return list() + raise TypeError(f"_get_list unexpected type of {value}") def __get_syc_setup(self) -> dict: + """ + This function is for backward-compatibility reasons for 24.1 and 24.2 versions. + It tells Fluent to write the SCP file and then parses it to get the setup + information. The SCP file is then deleted. + With newer versions, settings APIs can be used directly, without having + to write the SCP file at all. + """ + def get_scp_string() -> str: """Get the SCP file contents in the form of an XML string.""" scp_file_name = "fluent.scp" - self._solver.setup.models.system_coupling.write_scp_file( + self._solver.settings.setup.models.system_coupling.write_scp_file( file_name=scp_file_name ) diff --git a/tests/test_systemcoupling.py b/tests/test_systemcoupling.py index cc969a056e2..5e730c47a68 100644 --- a/tests/test_systemcoupling.py +++ b/tests/test_systemcoupling.py @@ -1,9 +1,6 @@ import pytest - -@pytest.mark.fluent_version(">=24.1") -def test_systemcoupling_mixing_elbow_settings(mixing_elbow_case_data_session): - """Very superficial test of System Coupling related settings.""" +def _test_systemcoupling_mixing_elbow_settings_common(mixing_elbow_case_data_session): solver = mixing_elbow_case_data_session # check participant type, analysis type, regions, and variables assert solver.system_coupling.participant_type == "FLUENT" @@ -14,3 +11,15 @@ def test_systemcoupling_mixing_elbow_settings(mixing_elbow_case_data_session): assert len(regions) >= 6 # [force, dsip, temp, htc, hflow, nwt, hrate, cond, lorentz-force] assert len(variables) >= 9 + + +@pytest.mark.fluent_version(">=25.1") +def test_systemcoupling_mixing_elbow_settings(mixing_elbow_case_data_session): + """Very superficial test of System Coupling related settings.""" + _test_systemcoupling_mixing_elbow_settings_common(mixing_elbow_case_data_session) + + +@pytest.mark.fluent_version("<25.1") +def test_systemcoupling_mixing_elbow_settings_legacy(mixing_elbow_case_data_session): + """Test legacy implementation of getting System Coupling related settings.""" + _test_systemcoupling_mixing_elbow_settings_common(mixing_elbow_case_data_session) From c35e24c5b668924efc8923bd30b2bbab6d8cba08 Mon Sep 17 00:00:00 2001 From: Oleg Chernukhin Date: Thu, 7 Nov 2024 16:03:27 -0500 Subject: [PATCH 2/7] feat: formatting --- src/ansys/fluent/core/systemcoupling.py | 56 +++++++++++++++++++------ 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/src/ansys/fluent/core/systemcoupling.py b/src/ansys/fluent/core/systemcoupling.py index 83da47ecbfc..63dbcfb6f9a 100644 --- a/src/ansys/fluent/core/systemcoupling.py +++ b/src/ansys/fluent/core/systemcoupling.py @@ -55,7 +55,9 @@ def __init__(self, solver): ) if self._solver.get_fluent_version() >= FluentVersion.v251: # enable feature to be able to make System Coupling settings APIs calls - self._solver.scheme_eval.scheme_eval("(enable-feature 'sc/participant-info)") + self._solver.scheme_eval.scheme_eval( + "(enable-feature 'sc/participant-info)" + ) @property def participant_type(self) -> str: @@ -67,11 +69,21 @@ def get_variables(self) -> List[Variable]: if self._solver.get_fluent_version() >= FluentVersion.v251: variables = list() - region_names = self._solver.settings.setup.models.system_coupling.get_all_regions() + region_names = ( + self._solver.settings.setup.models.system_coupling.get_all_regions() + ) variable_names = set() for region_name in region_names: - in_var_names = self._get_list(self._solver.settings.setup.models.system_coupling.get_input_vars(region_name=region_name)) - out_var_names = self._get_list(self._solver.settings.setup.models.system_coupling.get_output_vars(region_name=region_name)) + in_var_names = self._get_list( + self._solver.settings.setup.models.system_coupling.get_input_vars( + region_name=region_name + ) + ) + out_var_names = self._get_list( + self._solver.settings.setup.models.system_coupling.get_output_vars( + region_name=region_name + ) + ) variable_names.update(in_var_names) variable_names.update(out_var_names) variable_names = sorted(list(variable_names)) @@ -80,9 +92,15 @@ def get_variables(self) -> List[Variable]: Variable( name=variable_name, display_name=self._get_display_name(variable_name), - tensor_type=self._solver.settings.setup.models.system_coupling.get_tensor_type(variable_name=variable_name), - is_extensive=self._solver.settings.setup.models.system_coupling.is_extensive_var(variable_name=variable_name), - location=self._solver.settings.setup.models.system_coupling.get_data_location(variable_name=variable_name), + tensor_type=self._solver.settings.setup.models.system_coupling.get_tensor_type( + variable_name=variable_name + ), + is_extensive=self._solver.settings.setup.models.system_coupling.is_extensive_var( + variable_name=variable_name + ), + location=self._solver.settings.setup.models.system_coupling.get_data_location( + variable_name=variable_name + ), quantity_type=self._get_quantity_type(variable_name), ) ) @@ -95,16 +113,28 @@ def get_regions(self) -> List[Region]: """Get regions.""" if self._solver.get_fluent_version() >= FluentVersion.v251: - region_names = self._solver.settings.setup.models.system_coupling.get_all_regions() + region_names = ( + self._solver.settings.setup.models.system_coupling.get_all_regions() + ) regions = list() for region_name in region_names: regions.append( Region( name=region_name, display_name=self._get_display_name(region_name), - topology=self._solver.settings.setup.models.system_coupling.get_topology(region_name=region_name), - input_variables=self._get_list(self._solver.settings.setup.models.system_coupling.get_input_vars(region_name=region_name)), - output_variables=self._get_list(self._solver.settings.setup.models.system_coupling.get_output_vars(region_name=region_name)), + topology=self._solver.settings.setup.models.system_coupling.get_topology( + region_name=region_name + ), + input_variables=self._get_list( + self._solver.settings.setup.models.system_coupling.get_input_vars( + region_name=region_name + ) + ), + output_variables=self._get_list( + self._solver.settings.setup.models.system_coupling.get_output_vars( + region_name=region_name + ) + ), ) ) return regions @@ -115,7 +145,9 @@ def get_regions(self) -> List[Region]: def get_analysis_type(self) -> str: """Get analysis type.""" if self._solver.get_fluent_version() >= FluentVersion.v251: - return self._solver.settings.setup.models.system_coupling.get_analysis_type() + return ( + self._solver.settings.setup.models.system_coupling.get_analysis_type() + ) else: # maintains back-compatibility for 24.1 and 24.2 return self.__get_syc_setup()["analysis-type"] From a6264d17a361c3652adc9d37bfcdb116d2d5909b Mon Sep 17 00:00:00 2001 From: Oleg Chernukhin Date: Fri, 8 Nov 2024 09:48:58 -0500 Subject: [PATCH 3/7] feat: test improvement --- tests/test_systemcoupling.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_systemcoupling.py b/tests/test_systemcoupling.py index 5e730c47a68..3c22d0674f0 100644 --- a/tests/test_systemcoupling.py +++ b/tests/test_systemcoupling.py @@ -1,5 +1,6 @@ import pytest + def _test_systemcoupling_mixing_elbow_settings_common(mixing_elbow_case_data_session): solver = mixing_elbow_case_data_session # check participant type, analysis type, regions, and variables @@ -19,7 +20,7 @@ def test_systemcoupling_mixing_elbow_settings(mixing_elbow_case_data_session): _test_systemcoupling_mixing_elbow_settings_common(mixing_elbow_case_data_session) -@pytest.mark.fluent_version("<25.1") +@pytest.mark.fluent_version(">=24.1,<25.1") def test_systemcoupling_mixing_elbow_settings_legacy(mixing_elbow_case_data_session): """Test legacy implementation of getting System Coupling related settings.""" _test_systemcoupling_mixing_elbow_settings_common(mixing_elbow_case_data_session) From 4905bf6793042de3db63b2f9843a1cf049bc729b Mon Sep 17 00:00:00 2001 From: Oleg Chernukhin Date: Mon, 11 Nov 2024 12:29:13 -0500 Subject: [PATCH 4/7] feat: add a lower-level test --- tests/test_systemcoupling.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_systemcoupling.py b/tests/test_systemcoupling.py index 3c22d0674f0..1d9c4e73080 100644 --- a/tests/test_systemcoupling.py +++ b/tests/test_systemcoupling.py @@ -1,5 +1,18 @@ import pytest +@pytest.mark.fluent_version(">=25.1") +def test_systemcoupling_mixing_elbow_settings_apis(mixing_elbow_case_data_session): + """Test System Coupling related settings APIs""" + solver = mixing_elbow_case_data_session + # enable the feature flag to be able to make the queries + solver.scheme_eval.scheme_eval("(enable-feature 'sc/participant-info)") + elbow_fluid = "elbow_fluid" + region_names = solver.settings.setup.models.system_coupling.get_all_regions() + assert elbow_fluid in region_names + # elbow fluid must be a volume + assert solver.settings.setup.models.system_coupling.get_topology( + region_name = elbow_fluid) == "Volume" + def _test_systemcoupling_mixing_elbow_settings_common(mixing_elbow_case_data_session): solver = mixing_elbow_case_data_session From 85e36379ef38a259250d496d1b89cea15247ccbe Mon Sep 17 00:00:00 2001 From: Oleg Chernukhin Date: Mon, 11 Nov 2024 13:39:36 -0500 Subject: [PATCH 5/7] feat: formatting --- src/ansys/fluent/core/systemcoupling.py | 2 +- tests/test_systemcoupling.py | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ansys/fluent/core/systemcoupling.py b/src/ansys/fluent/core/systemcoupling.py index 63dbcfb6f9a..182acea06a7 100644 --- a/src/ansys/fluent/core/systemcoupling.py +++ b/src/ansys/fluent/core/systemcoupling.py @@ -195,7 +195,7 @@ def _get_display_name(internal_name: str) -> str: def _get_list(value: list | None) -> list: if isinstance(value, list): return value - elif value == None: + elif value is None: return list() raise TypeError(f"_get_list unexpected type of {value}") diff --git a/tests/test_systemcoupling.py b/tests/test_systemcoupling.py index 1d9c4e73080..9874c429809 100644 --- a/tests/test_systemcoupling.py +++ b/tests/test_systemcoupling.py @@ -1,5 +1,6 @@ import pytest + @pytest.mark.fluent_version(">=25.1") def test_systemcoupling_mixing_elbow_settings_apis(mixing_elbow_case_data_session): """Test System Coupling related settings APIs""" @@ -10,8 +11,12 @@ def test_systemcoupling_mixing_elbow_settings_apis(mixing_elbow_case_data_sessio region_names = solver.settings.setup.models.system_coupling.get_all_regions() assert elbow_fluid in region_names # elbow fluid must be a volume - assert solver.settings.setup.models.system_coupling.get_topology( - region_name = elbow_fluid) == "Volume" + assert ( + solver.settings.setup.models.system_coupling.get_topology( + region_name=elbow_fluid + ) + == "Volume" + ) def _test_systemcoupling_mixing_elbow_settings_common(mixing_elbow_case_data_session): From 85684daaf6d25ce0268119b51e1b2fb8d79f2cf8 Mon Sep 17 00:00:00 2001 From: Mainak Kundu Date: Wed, 13 Nov 2024 11:37:30 -0500 Subject: [PATCH 6/7] fix: query execution --- src/ansys/fluent/core/solver/flobject.py | 9 +++++++-- tests/test_systemcoupling.py | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ansys/fluent/core/solver/flobject.py b/src/ansys/fluent/core/solver/flobject.py index 4fb4948ecc9..13e0990b384 100644 --- a/src/ansys/fluent/core/solver/flobject.py +++ b/src/ansys/fluent/core/solver/flobject.py @@ -1803,8 +1803,13 @@ class Query(Action): def __call__(self, **kwds): """Call a query with the specified keyword arguments.""" - newkwds = _get_new_keywords(self, **kwds) - return self.flproxy.execute_query(self._parent.path, self.obj_name, **newkwds) + kwds = _get_new_keywords(self, **kwds) + scmKwds = {} + for arg, value in kwds.items(): + argument = getattr(self, arg) + # Convert key-value to Scheme key-value + scmKwds[argument.fluent_name] = argument.to_scheme_keys(value) + return self.flproxy.execute_query(self._parent.path, self.obj_name, **scmKwds) _baseTypes = { diff --git a/tests/test_systemcoupling.py b/tests/test_systemcoupling.py index 9874c429809..8f57380a6f9 100644 --- a/tests/test_systemcoupling.py +++ b/tests/test_systemcoupling.py @@ -7,7 +7,7 @@ def test_systemcoupling_mixing_elbow_settings_apis(mixing_elbow_case_data_sessio solver = mixing_elbow_case_data_session # enable the feature flag to be able to make the queries solver.scheme_eval.scheme_eval("(enable-feature 'sc/participant-info)") - elbow_fluid = "elbow_fluid" + elbow_fluid = "elbow-fluid" region_names = solver.settings.setup.models.system_coupling.get_all_regions() assert elbow_fluid in region_names # elbow fluid must be a volume From b632e21511dad9ed0d28f11f9a696f38c61a0f06 Mon Sep 17 00:00:00 2001 From: Oleg Chernukhin Date: Wed, 13 Nov 2024 13:29:50 -0500 Subject: [PATCH 7/7] feat: update test - remove displacement from list of vars --- tests/test_systemcoupling.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_systemcoupling.py b/tests/test_systemcoupling.py index 8f57380a6f9..639e20a380c 100644 --- a/tests/test_systemcoupling.py +++ b/tests/test_systemcoupling.py @@ -28,8 +28,8 @@ def _test_systemcoupling_mixing_elbow_settings_common(mixing_elbow_case_data_ses variables = solver.system_coupling.get_variables() # [wall-inlet, wall-elbow, elbow-fluid, hot-inlet, cold-inlet, outlet] assert len(regions) >= 6 - # [force, dsip, temp, htc, hflow, nwt, hrate, cond, lorentz-force] - assert len(variables) >= 9 + # [force, temp, htc, hflow, nwt, hrate, e-cond, lorentz-force] + assert len(variables) >= 8 @pytest.mark.fluent_version(">=25.1")