From 2e84af05c1c5fb9c83e5fa109a0df62cce468570 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Wed, 19 Feb 2025 19:05:35 +0530 Subject: [PATCH 01/10] stash chages. --- codegen/allapigen.py | 5 + doc/datamodel_rstgen.py | 3 +- src/ansys/fluent/core/codegen/__init__.py | 1 + src/ansys/fluent/core/codegen/datamodelgen.py | 13 +++ src/ansys/fluent/core/session_base_meshing.py | 102 ++++++++++++++++-- src/ansys/fluent/core/session_pure_meshing.py | 6 ++ tests/test_codegen.py | 2 + 7 files changed, 125 insertions(+), 7 deletions(-) diff --git a/codegen/allapigen.py b/codegen/allapigen.py index 05ba2895d757..97d67695051b 100644 --- a/codegen/allapigen.py +++ b/codegen/allapigen.py @@ -1,5 +1,7 @@ """Helper module to generate Fluent API classes.""" +import os +os.environ["PYFLUENT_FLUENT_ROOT"] = r"C:\ANSYSDev\ANSYSDev\vNNN\fluent" import argparse from time import time @@ -21,6 +23,9 @@ StaticInfoType.DATAMODEL_WORKFLOW: meshing._datamodel_service_se.get_static_info( "workflow" ), + StaticInfoType.DATAMODEL_WORKFLOW_API: meshing._datamodel_service_se.get_static_info( + "workflow_api" + ), StaticInfoType.DATAMODEL_MESHING: meshing._datamodel_service_se.get_static_info( "meshing" ), diff --git a/doc/datamodel_rstgen.py b/doc/datamodel_rstgen.py index cc07aab3812a..4c8b694336e4 100644 --- a/doc/datamodel_rstgen.py +++ b/doc/datamodel_rstgen.py @@ -16,6 +16,7 @@ def generate_meshing_datamodels(): "PMFileManagement", "preferences", "workflow", + "workflow_api", ] for meshing_datamodel in meshing_datamodels: try: @@ -36,7 +37,7 @@ def generate_solver_datamodels(): """Generate solver datamodel RST files.""" solver_datamodel_roots = [] available_datamodels = [] - solver_datamodels = ["flicing", "preferences", "solverworkflow", "workflow"] + solver_datamodels = ["flicing", "preferences", "solverworkflow", "workflow", "workflow_api"] for solver_datamodel in solver_datamodels: try: datamodel = importlib.import_module( diff --git a/src/ansys/fluent/core/codegen/__init__.py b/src/ansys/fluent/core/codegen/__init__.py index 6e188f5ca259..3c4d4b5c13e0 100644 --- a/src/ansys/fluent/core/codegen/__init__.py +++ b/src/ansys/fluent/core/codegen/__init__.py @@ -32,6 +32,7 @@ class StaticInfoType(Enum): TUI_SOLVER = auto() TUI_MESHING = auto() DATAMODEL_WORKFLOW = auto() + DATAMODEL_WORKFLOW_API = auto() DATAMODEL_MESHING = auto() DATAMODEL_PART_MANAGEMENT = auto() DATAMODEL_PM_FILE_MANAGEMENT = auto() diff --git a/src/ansys/fluent/core/codegen/datamodelgen.py b/src/ansys/fluent/core/codegen/datamodelgen.py index 76da17c7ed2b..5749ee4938b5 100644 --- a/src/ansys/fluent/core/codegen/datamodelgen.py +++ b/src/ansys/fluent/core/codegen/datamodelgen.py @@ -191,6 +191,16 @@ def __init__(self, version, static_infos: dict, verbose: bool = False): ), self.version, ) + if StaticInfoType.DATAMODEL_WORKFLOW_API in static_infos: + self._static_info["workflow_api"] = DataModelStaticInfo( + StaticInfoType.DATAMODEL_WORKFLOW_API, + "workflow_api", + ( + "meshing", + "solver", + ), + self.version, + ) if StaticInfoType.DATAMODEL_MESHING in static_infos: self._static_info["meshing"] = DataModelStaticInfo( StaticInfoType.DATAMODEL_MESHING, "meshing", ("meshing",), self.version @@ -477,6 +487,9 @@ def generate(version, static_infos: dict, verbose: bool = False): StaticInfoType.DATAMODEL_WORKFLOW: meshing._datamodel_service_se.get_static_info( "workflow" ), + StaticInfoType.DATAMODEL_WORKFLOW_API: meshing._datamodel_service_se.get_static_info( + "workflow_api" + ), StaticInfoType.DATAMODEL_MESHING: meshing._datamodel_service_se.get_static_info( "meshing" ), diff --git a/src/ansys/fluent/core/session_base_meshing.py b/src/ansys/fluent/core/session_base_meshing.py index 2b12186293d4..9ac42e84f123 100644 --- a/src/ansys/fluent/core/session_base_meshing.py +++ b/src/ansys/fluent/core/session_base_meshing.py @@ -75,6 +75,7 @@ def __init__( self._fluent_version = fluent_version self._meshing_utilities = None self._old_workflow = None + self._workflow_api = None self._part_management = None self._pm_file_management = None self._preferences = None @@ -148,15 +149,24 @@ def workflow(self): self._old_workflow = _make_datamodel_module(self, "workflow") return self._old_workflow + @property + def workflow_api(self): + if self._workflow_api is None: + self._workflow_api = _make_datamodel_module(self, "workflow_api") + return self._workflow_api + def watertight_workflow(self, initialize: bool = True): """Datamodel root of workflow.""" - self._current_workflow = WorkflowMode.WATERTIGHT_MESHING_MODE.value( - _make_datamodel_module(self, "workflow"), - self.meshing, - self.get_fluent_version(), - initialize, - ) + self._current_workflow = WorkflowWrapper(_make_datamodel_module(self, "workflow_api")) + self._current_workflow.initialize_workflow(workflow_type="Watertight Geometry") return self._current_workflow + # self._current_workflow = WorkflowMode.WATERTIGHT_MESHING_MODE.value( + # _make_datamodel_module(self, "workflow"), + # self.meshing, + # self.get_fluent_version(), + # initialize, + # ) + # return self._current_workflow def fault_tolerant_workflow(self, initialize: bool = True): """Datamodel root of workflow.""" @@ -269,3 +279,83 @@ def preferences(self): if self._preferences is None: self._preferences = _make_datamodel_module(self, "preferences") return self._preferences + + +class WorkflowWrapper: + def __init__(self, workflow): + self.workflow = workflow + + def __getattr__(self, name): + try: + return getattr(self.workflow, name) + except AttributeError as ex: + _task_object= self.workflow.task_object.get(name) + if _task_object: + return TaskWrapper(_task_object) + else: + raise ex + +class TaskWrapper: + def __init__(self, task): + self.task = task + + def __getattr__(self, name): + try: + return getattr(self.task, name) + except AttributeError as ex: + if name in self.task.arguments(): + return ArgumentWrapper(self.task, name, self.task.arguments().get(name)) + else: + raise ex + + def __call__(self, *args, **kwargs): + self.task.execute() + + +class ArgumentWrapper: + def __init__(self, task, arg_name, arg_state): + self.__dict__.update( + dict( + tash=task, + arg_name=arg_name, + arg_state=arg_state, + ) + ) + + def __getattr__(self, name): + # try: + # return getattr(self.task.arguments()[self.arg_name], name) + # except AttributeError as ex: + try: + if type(self.arg_state) is dict: + return ArgumentWrapper(self.task, name, self.arg_state[name]) + else: + return self.arg_state[name] + except KeyError: + raise AttributeError(f"{self.arg_name} has no object named {name}.") + + # def __setattr__(self, name, value): + # try: + # # if type(self.arg_state) is dict: + # # ArgumentWrapper(self.task, self.arg_state[name]) + # # else: + # self.task.arguments.update_dict(dict(name=value)) + # except KeyError as ex: + # raise AttributeError(f"No object named {name}.") from ex + + + def __call__(self, *args, **kwargs): + return self.arg_state + + +# class SubArgumentWrapper: +# def __init__(self, arg_state): +# self.arg_state = arg_state +# +# def __getattr__(self, name): +# if type(self.arg_state[name]) is dict: +# return SubArgumentWrapper(self.arg_state[name]) +# else: +# return self.arg_state[name] + + diff --git a/src/ansys/fluent/core/session_pure_meshing.py b/src/ansys/fluent/core/session_pure_meshing.py index 832029ec0cb2..ebbd8c73d627 100644 --- a/src/ansys/fluent/core/session_pure_meshing.py +++ b/src/ansys/fluent/core/session_pure_meshing.py @@ -49,6 +49,7 @@ class PureMeshing(BaseSession): _rules = [ "workflow", + "workflow_api", "meshing", "MeshingUtilities", "PartManagement", @@ -145,6 +146,11 @@ def workflow(self): """Datamodel root of workflow.""" return self._base_meshing.workflow + @property + def workflow_api(self): + """Datamodel root of workflow.""" + return self._base_meshing.workflow_api + def watertight(self): """Get a new watertight workflow.""" return self._base_meshing.watertight_workflow() diff --git a/tests/test_codegen.py b/tests/test_codegen.py index c1541d3a5858..0376e8bd401e 100644 --- a/tests/test_codegen.py +++ b/tests/test_codegen.py @@ -174,6 +174,7 @@ def test_codegen_with_tui_solver_static_info(mode, monkeypatch): _static_info_type_by_rules = { "workflow": StaticInfoType.DATAMODEL_WORKFLOW, + "workflow_api": StaticInfoType.DATAMODEL_WORKFLOW_API, "meshing": StaticInfoType.DATAMODEL_MESHING, "PartManagement": StaticInfoType.DATAMODEL_PART_MANAGEMENT, "PMFileManagement": StaticInfoType.DATAMODEL_PM_FILE_MANAGEMENT, @@ -371,6 +372,7 @@ def test_codegen_with_datamodel_static_info(monkeypatch, rules): api_tree_expected = {"": {}, "": {}} if rules in [ "workflow", + "workflow_api", "meshing", "PartManagement", "PMFileManagement", From cd9f1a67e828dc774372e56240759bd747d3efe1 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Mon, 18 Aug 2025 10:41:47 +0530 Subject: [PATCH 02/10] workflow_api -> meshing_workflow --- codegen/allapigen.py | 10 +- doc/datamodel_rstgen.py | 2 +- src/ansys/fluent/core/codegen/__init__.py | 2 +- src/ansys/fluent/core/codegen/datamodelgen.py | 21 ++- src/ansys/fluent/core/session_base_meshing.py | 162 +++++++++--------- src/ansys/fluent/core/session_meshing.py | 5 + src/ansys/fluent/core/session_pure_meshing.py | 6 +- .../fluent/core/session_pure_meshing.pyi | 5 + 8 files changed, 109 insertions(+), 104 deletions(-) diff --git a/codegen/allapigen.py b/codegen/allapigen.py index d737e49b91ad..f87ea2deccd2 100644 --- a/codegen/allapigen.py +++ b/codegen/allapigen.py @@ -1,7 +1,5 @@ """Helper module to generate Fluent API classes.""" -import os -os.environ["PYFLUENT_FLUENT_ROOT"] = r"C:\ANSYSDev\ANSYSDev\vNNN\fluent" import argparse from time import time @@ -18,14 +16,12 @@ gt_222 = FluentVersion(version) > FluentVersion.v222 ge_231 = FluentVersion(version) >= FluentVersion.v231 ge_242 = FluentVersion(version) >= FluentVersion.v242 + ge_261 = FluentVersion(version) >= FluentVersion.v261 static_infos = { StaticInfoType.DATAMODEL_WORKFLOW: meshing._datamodel_service_se.get_static_info( "workflow" ), - StaticInfoType.DATAMODEL_WORKFLOW_API: meshing._datamodel_service_se.get_static_info( - "workflow_api" - ), StaticInfoType.DATAMODEL_MESHING: meshing._datamodel_service_se.get_static_info( "meshing" ), @@ -44,6 +40,10 @@ static_infos[StaticInfoType.DATAMODEL_MESHING_UTILITIES] = ( meshing._datamodel_service_se.get_static_info("MeshingUtilities") ) + if ge_261: + static_infos[StaticInfoType.DATAMODEL_MESHING_WORKFLOW] = ( + meshing._datamodel_service_se.get_static_info("meshing_workflow") + ) meshing.exit() solver = launch_fluent( diff --git a/doc/datamodel_rstgen.py b/doc/datamodel_rstgen.py index d35511bb8141..dd38d431f1b8 100644 --- a/doc/datamodel_rstgen.py +++ b/doc/datamodel_rstgen.py @@ -16,7 +16,7 @@ def generate_meshing_datamodels(): "pm_file_management", "preferences", "workflow", - "workflow_api", + "meshing_workflow", ] for meshing_datamodel in meshing_datamodels: try: diff --git a/src/ansys/fluent/core/codegen/__init__.py b/src/ansys/fluent/core/codegen/__init__.py index 3c4d4b5c13e0..55e1949c9f6e 100644 --- a/src/ansys/fluent/core/codegen/__init__.py +++ b/src/ansys/fluent/core/codegen/__init__.py @@ -32,7 +32,7 @@ class StaticInfoType(Enum): TUI_SOLVER = auto() TUI_MESHING = auto() DATAMODEL_WORKFLOW = auto() - DATAMODEL_WORKFLOW_API = auto() + DATAMODEL_MESHING_WORKFLOW = auto() DATAMODEL_MESHING = auto() DATAMODEL_PART_MANAGEMENT = auto() DATAMODEL_PM_FILE_MANAGEMENT = auto() diff --git a/src/ansys/fluent/core/codegen/datamodelgen.py b/src/ansys/fluent/core/codegen/datamodelgen.py index 9f56a7fe1ad7..2b90a9c12aa2 100644 --- a/src/ansys/fluent/core/codegen/datamodelgen.py +++ b/src/ansys/fluent/core/codegen/datamodelgen.py @@ -188,6 +188,7 @@ def _build_command_query_docstring( "MeshingUtilities": "meshing_utilities", "flicing": "flicing", "solverworkflow": "solver_workflow", + "meshing_workflow": "meshing_workflow", } @@ -242,14 +243,11 @@ def __init__(self, version, static_infos: dict, verbose: bool = False): ), self.version, ) - if StaticInfoType.DATAMODEL_WORKFLOW_API in static_infos: - self._static_info["workflow_api"] = DataModelStaticInfo( - StaticInfoType.DATAMODEL_WORKFLOW_API, - "workflow_api", - ( - "meshing", - "solver", - ), + if StaticInfoType.DATAMODEL_MESHING_WORKFLOW in static_infos: + self._static_info["meshing_workflow"] = DataModelStaticInfo( + StaticInfoType.DATAMODEL_MESHING_WORKFLOW, + "meshing_workflow", + ("meshing",), self.version, ) if StaticInfoType.DATAMODEL_MESHING in static_infos: @@ -608,9 +606,6 @@ def generate(version, static_infos: dict, verbose: bool = False): StaticInfoType.DATAMODEL_WORKFLOW: meshing._datamodel_service_se.get_static_info( "workflow" ), - StaticInfoType.DATAMODEL_WORKFLOW_API: meshing._datamodel_service_se.get_static_info( - "workflow_api" - ), StaticInfoType.DATAMODEL_MESHING: meshing._datamodel_service_se.get_static_info( "meshing" ), @@ -636,6 +631,10 @@ def generate(version, static_infos: dict, verbose: bool = False): static_infos[StaticInfoType.DATAMODEL_MESHING_UTILITIES] = ( meshing._datamodel_service_se.get_static_info("MeshingUtilities") ) + if FluentVersion(version) >= FluentVersion.v261: + static_infos[StaticInfoType.DATAMODEL_MESHING_WORKFLOW] = ( + meshing._datamodel_service_se.get_static_info("meshing_workflow") + ) parser = argparse.ArgumentParser( description="A script to write Fluent API files with an optional verbose output." ) diff --git a/src/ansys/fluent/core/session_base_meshing.py b/src/ansys/fluent/core/session_base_meshing.py index e7f58712c4e9..cbf6776ef8b2 100644 --- a/src/ansys/fluent/core/session_base_meshing.py +++ b/src/ansys/fluent/core/session_base_meshing.py @@ -72,7 +72,7 @@ def __init__( self._fluent_version = fluent_version self._meshing_utilities = None self._old_workflow = None - self._workflow_api = None + self._meshing_workflow = None self._part_management = None self._pm_file_management = None self._preferences = None @@ -129,23 +129,21 @@ def workflow(self): return self._old_workflow @property - def workflow_api(self): - if self._workflow_api is None: - self._workflow_api = _make_datamodel_module(self, "workflow_api") - return self._workflow_api + def meshing_workflow(self): + """Full API to meshing and meshing_workflow.""" + if self._meshing_workflow is None: + self._meshing_workflow = _make_datamodel_module(self, "meshing_workflow") + return self._meshing_workflow def watertight_workflow(self, initialize: bool = True): """Datamodel root of workflow.""" - self._current_workflow = WorkflowWrapper(_make_datamodel_module(self, "workflow_api")) - self._current_workflow.initialize_workflow(workflow_type="Watertight Geometry") + self._current_workflow = WorkflowMode.WATERTIGHT_MESHING_MODE.value( + _make_datamodel_module(self, "workflow"), + self.meshing, + self.get_fluent_version(), + initialize, + ) return self._current_workflow - # self._current_workflow = WorkflowMode.WATERTIGHT_MESHING_MODE.value( - # _make_datamodel_module(self, "workflow"), - # self.meshing, - # self.get_fluent_version(), - # initialize, - # ) - # return self._current_workflow def fault_tolerant_workflow(self, initialize: bool = True): """Datamodel root of workflow.""" @@ -260,73 +258,73 @@ def preferences(self): return self._preferences -class WorkflowWrapper: - def __init__(self, workflow): - self.workflow = workflow - - def __getattr__(self, name): - try: - return getattr(self.workflow, name) - except AttributeError as ex: - _task_object= self.workflow.task_object.get(name) - if _task_object: - return TaskWrapper(_task_object) - else: - raise ex - -class TaskWrapper: - def __init__(self, task): - self.task = task - - def __getattr__(self, name): - try: - return getattr(self.task, name) - except AttributeError as ex: - if name in self.task.arguments(): - return ArgumentWrapper(self.task, name, self.task.arguments().get(name)) - else: - raise ex - - def __call__(self, *args, **kwargs): - self.task.execute() - - -class ArgumentWrapper: - def __init__(self, task, arg_name, arg_state): - self.__dict__.update( - dict( - tash=task, - arg_name=arg_name, - arg_state=arg_state, - ) - ) - - def __getattr__(self, name): - # try: - # return getattr(self.task.arguments()[self.arg_name], name) - # except AttributeError as ex: - try: - if type(self.arg_state) is dict: - return ArgumentWrapper(self.task, name, self.arg_state[name]) - else: - return self.arg_state[name] - except KeyError: - raise AttributeError(f"{self.arg_name} has no object named {name}.") - - # def __setattr__(self, name, value): - # try: - # # if type(self.arg_state) is dict: - # # ArgumentWrapper(self.task, self.arg_state[name]) - # # else: - # self.task.arguments.update_dict(dict(name=value)) - # except KeyError as ex: - # raise AttributeError(f"No object named {name}.") from ex - - - def __call__(self, *args, **kwargs): - return self.arg_state - - +# class WorkflowWrapper: +# def __init__(self, workflow): +# self.workflow = workflow +# +# def __getattr__(self, name): +# try: +# return getattr(self.workflow, name) +# except AttributeError as ex: +# _task_object = self.workflow.task_object.get(name) +# if _task_object: +# return TaskWrapper(_task_object) +# else: +# raise ex +# +# +# class TaskWrapper: +# def __init__(self, task): +# self.task = task +# +# def __getattr__(self, name): +# try: +# return getattr(self.task, name) +# except AttributeError as ex: +# if name in self.task.arguments(): +# return ArgumentWrapper(self.task, name, self.task.arguments().get(name)) +# else: +# raise ex +# +# def __call__(self, *args, **kwargs): +# self.task.execute() +# +# +# class ArgumentWrapper: +# def __init__(self, task, arg_name, arg_state): +# self.__dict__.update( +# dict( +# tash=task, +# arg_name=arg_name, +# arg_state=arg_state, +# ) +# ) +# +# def __getattr__(self, name): +# # try: +# # return getattr(self.task.arguments()[self.arg_name], name) +# # except AttributeError as ex: +# try: +# if type(self.arg_state) is dict: +# return ArgumentWrapper(self.task, name, self.arg_state[name]) +# else: +# return self.arg_state[name] +# except KeyError: +# raise AttributeError(f"{self.arg_name} has no object named {name}.") +# +# def __setattr__(self, name, value): +# try: +# # if type(self.arg_state) is dict: +# # ArgumentWrapper(self.task, self.arg_state[name]) +# # else: +# self.task.arguments.update_dict(dict(name=value)) +# except KeyError as ex: +# raise AttributeError(f"No object named {name}.") from ex +# +# def __call__(self, *args, **kwargs): +# return self.arg_state +# +# # class SubArgumentWrapper: # def __init__(self, arg_state): # self.arg_state = arg_state @@ -336,5 +334,3 @@ def __call__(self, *args, **kwargs): # return SubArgumentWrapper(self.arg_state[name]) # else: # return self.arg_state[name] - - diff --git a/src/ansys/fluent/core/session_meshing.py b/src/ansys/fluent/core/session_meshing.py index 901d5a149a15..12c6fd4a05d7 100644 --- a/src/ansys/fluent/core/session_meshing.py +++ b/src/ansys/fluent/core/session_meshing.py @@ -127,6 +127,11 @@ def workflow(self): """Workflow datamodel root.""" return super(Meshing, self).workflow + @property + def meshing_workflow(self): + """Full API to meshing and meshing_workflow.""" + return super(Meshing, self).meshing_workflow + @property def PartManagement(self): """Part management datamodel root.""" diff --git a/src/ansys/fluent/core/session_pure_meshing.py b/src/ansys/fluent/core/session_pure_meshing.py index e356a4b31e9e..62368e2e3fca 100644 --- a/src/ansys/fluent/core/session_pure_meshing.py +++ b/src/ansys/fluent/core/session_pure_meshing.py @@ -148,9 +148,9 @@ def workflow(self): return self._base_meshing.workflow @property - def workflow_api(self): - """Datamodel root of workflow.""" - return self._base_meshing.workflow_api + def meshing_workflow(self): + """Full API to meshing and meshing_workflow.""" + return self._base_meshing.meshing_workflow def watertight(self): """Get a new watertight workflow.""" diff --git a/src/ansys/fluent/core/session_pure_meshing.pyi b/src/ansys/fluent/core/session_pure_meshing.pyi index d4bfea5052c7..33e94fa92a4e 100644 --- a/src/ansys/fluent/core/session_pure_meshing.pyi +++ b/src/ansys/fluent/core/session_pure_meshing.pyi @@ -34,6 +34,9 @@ from ansys.fluent.core.generated.datamodel_252.preferences import ( Root as preferences_root, ) from ansys.fluent.core.generated.datamodel_252.workflow import Root as workflow_root +from ansys.fluent.core.generated.datamodel_261.meshing_workflow import ( + Root as meshing_workflow_root, +) from ansys.fluent.core.generated.meshing.tui_252 import main_menu class PureMeshing: @@ -45,6 +48,8 @@ class PureMeshing: def meshing_utilities(self) -> meshing_utilities_root: ... @property def workflow(self) -> workflow_root: ... + @property + def meshing_workflow(self) -> meshing_workflow_root: ... def watertight(self): ... def fault_tolerant(self): ... def two_dimensional_meshing(self): ... From e3c13f8015fd82a631b086a576bedc4d3388fd42 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee <109645853+prmukherj@users.noreply.github.com> Date: Mon, 18 Aug 2025 10:44:20 +0530 Subject: [PATCH 03/10] Update src/ansys/fluent/core/session_pure_meshing.py --- src/ansys/fluent/core/session_pure_meshing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ansys/fluent/core/session_pure_meshing.py b/src/ansys/fluent/core/session_pure_meshing.py index 62368e2e3fca..bfe5fcf94b3a 100644 --- a/src/ansys/fluent/core/session_pure_meshing.py +++ b/src/ansys/fluent/core/session_pure_meshing.py @@ -50,7 +50,7 @@ class PureMeshing(BaseSession): _rules = [ "workflow", - "workflow_api", + "meshing_workflow", "meshing", "MeshingUtilities", "PartManagement", From 87e397e2760cf76fa82017983417c36c13b06cac Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee <109645853+prmukherj@users.noreply.github.com> Date: Mon, 18 Aug 2025 10:45:55 +0530 Subject: [PATCH 04/10] Update tests/test_codegen.py --- tests/test_codegen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_codegen.py b/tests/test_codegen.py index 438c20204ed9..9cf86371a3a5 100644 --- a/tests/test_codegen.py +++ b/tests/test_codegen.py @@ -175,7 +175,7 @@ def test_codegen_with_tui_solver_static_info(mode, monkeypatch): _static_info_type_by_rules = { "workflow": StaticInfoType.DATAMODEL_WORKFLOW, - "workflow_api": StaticInfoType.DATAMODEL_WORKFLOW_API, + "meshing_workflow": StaticInfoType.DATAMODEL_MESHING_WORKFLOW, "meshing": StaticInfoType.DATAMODEL_MESHING, "PartManagement": StaticInfoType.DATAMODEL_PART_MANAGEMENT, "PMFileManagement": StaticInfoType.DATAMODEL_PM_FILE_MANAGEMENT, From f80488080bcb335a3691161f38763d6b2bf784b8 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee <109645853+prmukherj@users.noreply.github.com> Date: Mon, 18 Aug 2025 10:46:17 +0530 Subject: [PATCH 05/10] Update tests/test_codegen.py --- tests/test_codegen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_codegen.py b/tests/test_codegen.py index 9cf86371a3a5..be5fd439114c 100644 --- a/tests/test_codegen.py +++ b/tests/test_codegen.py @@ -412,7 +412,7 @@ def test_codegen_with_datamodel_static_info(monkeypatch, rules): api_tree_expected = {"": {}, "": {}} if rules in [ "workflow", - "workflow_api", + "meshing_workflow", "meshing", "PartManagement", "PMFileManagement", From c259abe5b225d584194347ce38528d71a3dbeee7 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Mon, 18 Aug 2025 05:20:37 +0000 Subject: [PATCH 06/10] chore: adding changelog file 3748.added.md [dependabot-skip] --- doc/changelog.d/3748.added.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/3748.added.md diff --git a/doc/changelog.d/3748.added.md b/doc/changelog.d/3748.added.md new file mode 100644 index 000000000000..cdee1b3b429c --- /dev/null +++ b/doc/changelog.d/3748.added.md @@ -0,0 +1 @@ +Updates for the client side dm-api. From af1078ace013105dc30a93dfcb37a2897c98f4c4 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Mon, 18 Aug 2025 14:06:47 +0530 Subject: [PATCH 07/10] Add test --- tests/test_server_meshing_workflow.py | 132 ++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 tests/test_server_meshing_workflow.py diff --git a/tests/test_server_meshing_workflow.py b/tests/test_server_meshing_workflow.py new file mode 100644 index 000000000000..1abb85e9e4ba --- /dev/null +++ b/tests/test_server_meshing_workflow.py @@ -0,0 +1,132 @@ +# Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import pytest + +from ansys.fluent.core import examples + + +@pytest.mark.fluent_version(">=26.1") +def test_new_watertight_workflow(new_meshing_session_wo_exit): + # Import geometry + import_file_name = examples.download_file( + "mixing_elbow.pmdb", "pyfluent/mixing_elbow" + ) + new_meshing_session_wo_exit.workflow.InitializeWorkflow( + WorkflowType="Watertight Geometry" + ) + watertight = new_meshing_session_wo_exit.meshing_workflow + watertight.task_object.import_geometry["Import Geometry"].arguments.file_name = ( + import_file_name + ) + assert ( + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.length_unit() + == "mm" + ) + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.length_unit.set_state("in") + assert ( + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.length_unit.get_state() + == "in" + ) + watertight.task_object.import_geometry["Import Geometry"].execute() + + # Add local sizing + watertight.task_object.add_local_sizing_wtm["Add Local Sizing"].add_child_to_task() + watertight.task_object.add_local_sizing_wtm["Add Local Sizing"].execute() + + # Generate surface mesh + watertight.task_object.create_surface_mesh[ + "Generate the Surface Mesh" + ].arguments.cfd_surface_mesh_controls.max_size = 0.3 + assert ( + watertight.task_object.create_surface_mesh[ + "Generate the Surface Mesh" + ].arguments.cfd_surface_mesh_controls.max_size() + == 0.3 + ) + watertight.task_object.create_surface_mesh["Generate the Surface Mesh"].execute() + + # Describe geometry + watertight.task_object.describe_geometry["Describe Geometry"].update_child_tasks( + setup_type_changed=False + ) + watertight.task_object.describe_geometry[ + "Describe Geometry" + ].arguments.setup_type.set_state( + "The geometry consists of only fluid regions with no voids" + ) + watertight.task_object.describe_geometry["Describe Geometry"].update_child_tasks( + setup_type_changed=False + ) + watertight.task_object.describe_geometry["Describe Geometry"].execute() + + # Update boundaries + watertight.task_object.update_boundaries[ + "Update Boundaries" + ].arguments.boundary_label_list.set_state(["wall-inlet"]) + watertight.task_object.update_boundaries[ + "Update Boundaries" + ].arguments.boundary_label_type_list.set_state(["wall"]) + watertight.task_object.update_boundaries[ + "Update Boundaries" + ].arguments.old_boundary_label_list.set_state(["wall-inlet"]) + watertight.task_object.update_boundaries[ + "Update Boundaries" + ].arguments.old_boundary_label_type_list.set_state(["velocity-inlet"]) + watertight.task_object.update_boundaries["Update Boundaries"].execute() + + # Update regions + watertight.task_object.update_regions["Update Regions"].execute() + + # Add boundary layers + watertight.task_object.add_boundary_layers[ + "Add Boundary Layers" + ].add_child_to_task() + watertight.task_object.add_boundary_layers[ + "Add Boundary Layers" + ].arguments.control_name.set_state("smooth-transition_1") + watertight.task_object.add_boundary_layers[ + "Add Boundary Layers" + ].insert_compound_child_task() + watertight.task_object.add_boundary_layers["Add Boundary Layers"].execute() + + # Generate volume mesh + watertight.task_object.create_volume_mesh[ + "Generate the Volume Mesh" + ].arguments.volume_fill.set_state("poly-hexcore") + watertight.task_object.create_volume_mesh[ + "Generate the Volume Mesh" + ].arguments.hex_max_cell_length = 0.3 + watertight.task_object.create_volume_mesh["Generate the Volume Mesh"].execute() + + # Switch to solution mode + solver = new_meshing_session_wo_exit.switch_to_solver() + assert solver.is_active() is True + assert new_meshing_session_wo_exit.is_active() is False + solver.exit() + assert solver.is_active() is False From 4f698155a09b4fcc1ee05e2b29f6d7a155e23c1d Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Mon, 18 Aug 2025 21:15:24 +0530 Subject: [PATCH 08/10] Update tests. --- tests/test_server_meshing_workflow.py | 428 ++++++++++++++++++++++++++ 1 file changed, 428 insertions(+) diff --git a/tests/test_server_meshing_workflow.py b/tests/test_server_meshing_workflow.py index 1abb85e9e4ba..5c6b47e42507 100644 --- a/tests/test_server_meshing_workflow.py +++ b/tests/test_server_meshing_workflow.py @@ -130,3 +130,431 @@ def test_new_watertight_workflow(new_meshing_session_wo_exit): assert new_meshing_session_wo_exit.is_active() is False solver.exit() assert solver.is_active() is False + + +def test_new_fault_tolerant_workflow(new_meshing_session_wo_exit): + meshing = new_meshing_session_wo_exit + + # Import CAD and part management + import_file_name = examples.download_file( + "exhaust_system.fmd", "pyfluent/exhaust_system" + ) + new_meshing_session_wo_exit.workflow.InitializeWorkflow( + WorkflowType="Fault-tolerant Meshing" + ) + fault_tolerant = meshing.meshing_workflow + meshing.PartManagement.InputFileChanged( + FilePath=import_file_name, IgnoreSolidNames=False, PartPerBody=False + ) + meshing.PMFileManagement.FileManager.LoadFiles() + meshing.PartManagement.Node["Meshing Model"].Copy( + Paths=[ + "/dirty_manifold-for-wrapper," + "1/dirty_manifold-for-wrapper,1/main,1", + "/dirty_manifold-for-wrapper," + + "1/dirty_manifold-for-wrapper,1/flow-pipe,1", + "/dirty_manifold-for-wrapper," + + "1/dirty_manifold-for-wrapper,1/outpipe3,1", + "/dirty_manifold-for-wrapper," + "1/dirty_manifold-for-wrapper,1/object2,1", + "/dirty_manifold-for-wrapper," + "1/dirty_manifold-for-wrapper,1/object1,1", + ] + ) + meshing.PartManagement.ObjectSetting["DefaultObjectSetting"].OneZonePer.set_state( + "part" + ) + fault_tolerant.task_object.import_cad_and_part_management[ + "Import CAD and Part Management" + ].arguments.context.set_state(0) + fault_tolerant.task_object.import_cad_and_part_management[ + "Import CAD and Part Management" + ].arguments.create_object_per = "Custom" + fault_tolerant.task_object.import_cad_and_part_management[ + "Import CAD and Part Management" + ].arguments.fmd_file_name.set_state(import_file_name) + fault_tolerant.task_object.import_cad_and_part_management[ + "Import CAD and Part Management" + ].arguments.file_loaded = True + fault_tolerant.task_object.import_cad_and_part_management[ + "Import CAD and Part Management" + ].arguments.object_setting = "DefaultObjectSetting" + fault_tolerant.task_object.import_cad_and_part_management[ + "Import CAD and Part Management" + ].execute() + + # Describe geometry and flow + fault_tolerant.task_object.describe_geometry_and_flow[ + "Describe Geometry and Flow" + ].arguments.add_enclosure.set_state(False) + fault_tolerant.task_object.describe_geometry_and_flow[ + "Describe Geometry and Flow" + ].arguments.close_caps = True + fault_tolerant.task_object.describe_geometry_and_flow[ + "Describe Geometry and Flow" + ].arguments.describe_geometry_and_flow_options.advanced_options = True + fault_tolerant.task_object.describe_geometry_and_flow[ + "Describe Geometry and Flow" + ].arguments.describe_geometry_and_flow_options.extract_edge_features = True + fault_tolerant.task_object.describe_geometry_and_flow[ + "Describe Geometry and Flow" + ].arguments.flow_type = "Internal flow through the object" + fault_tolerant.task_object.describe_geometry_and_flow[ + "Describe Geometry and Flow" + ].update_child_tasks(setup_type_changed=False) + fault_tolerant.task_object.describe_geometry_and_flow[ + "Describe Geometry and Flow" + ].execute() + + # Enclose fluid regions (capping) + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.patch_name.set_state("inlet-1") + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.selection_type.set_state("zone") + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.zone_selection_list.set_state(["inlet.1"]) + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].insert_compound_child_task() + fault_tolerant.task_object.capping["inlet-1"].execute() + + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.patch_name.set_state("inlet-2") + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.selection_type.set_state("zone") + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.zone_selection_list.set_state(["inlet.2"]) + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].insert_compound_child_task() + fault_tolerant.task_object.capping["inlet-2"].execute() + + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.patch_name.set_state("inlet-3") + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.selection_type.set_state("zone") + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.zone_selection_list.set_state(["inlet"]) + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].insert_compound_child_task() + fault_tolerant.task_object.capping["inlet-3"].execute() + + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.patch_name.set_state("outlet-1") + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.selection_type.set_state("zone") + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.zone_selection_list.set_state(["outlet"]) + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].arguments.zone_type.set_state("pressure-outlet") + fault_tolerant.task_object.capping[ + "Enclose Fluid Regions (Capping)" + ].insert_compound_child_task() + fault_tolerant.task_object.capping["outlet-1"].execute() + + # Extract edge features + fault_tolerant.task_object.extract_edge_features[ + "Extract Edge Features" + ].arguments.extract_edges_name.set_state("edge-group-1") + fault_tolerant.task_object.extract_edge_features[ + "Extract Edge Features" + ].arguments.extract_method_type.set_state("Intersection Loops") + fault_tolerant.task_object.extract_edge_features[ + "Extract Edge Features" + ].arguments.object_selection_list.set_state(["flow_pipe", "main"]) + fault_tolerant.task_object.extract_edge_features[ + "Extract Edge Features" + ].insert_compound_child_task() + fault_tolerant.task_object.extract_edge_features["edge-group-1"].execute() + + # Identify regions + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.show_coordinates = True + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.material_points_name.set_state("fluid-region-1") + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.selection_type.set_state("zone") + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.x.set_state(377.322045740589) + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.y.set_state(-176.800676988458) + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.z.set_state(-37.0764628583475) + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.zone_selection_list.set_state(["main.1"]) + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].insert_compound_child_task() + fault_tolerant.task_object.identify_regions["fluid-region-1"].execute() + + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.show_coordinates = True + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.material_points_name.set_state("void-region-1") + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.new_region_type.set_state("void") + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.object_selection_list.set_state( + ["inlet-1", "inlet-2", "inlet-3", "main"] + ) + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.x.set_state(374.722045740589) + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.y.set_state(-278.9775145640143) + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.z.set_state(-161.1700719416913) + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].arguments.zone_selection_list.set_state(["main.1"]) + fault_tolerant.task_object.identify_regions[ + "Identify Regions" + ].insert_compound_child_task() + fault_tolerant.task_object.identify_regions["void-region-1"].execute() + + # Define leakage threshold + fault_tolerant.task_object.define_leakage_threshold[ + "Define Leakage Threshold" + ].arguments.set_state( + { + "add_child": "yes", + "flip_direction": True, + "leakage_name": "leakage-1", + "plane_direction": "X", + "region_selection_single": "void-region-1", + } + ) + fault_tolerant.task_object.define_leakage_threshold[ + "Define Leakage Threshold" + ].insert_compound_child_task() + fault_tolerant.task_object.define_leakage_threshold["leakage-1"].execute() + + # Update regions settings + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_filter_categories.set_state(["2"] * 5 + ["1"] * 2) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_leakage_size_list.set_state(["none"] * 6 + ["6.4"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_linked_construction_surface_list.set_state( + ["n/a"] * 6 + ["no"] + ) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_mesh_method_list.set_state(["none"] * 6 + ["wrap"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_name_list.set_state( + [ + "main", + "flow_pipe", + "outpipe3", + "object2", + "object1", + "void-region-1", + "fluid-region-1", + ] + ) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_overset_componen_list.set_state(["no"] * 7) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_source_list.set_state(["object"] * 5 + ["mpt"] * 2) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_type_list.set_state(["void"] * 6 + ["fluid"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_volume_fill_list.set_state(["none"] * 6 + ["tet"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.filter_category.set_state("Identified Regions") + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_leakage_size_list.set_state([""]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_mesh_method_list.set_state(["wrap"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_name_list.set_state(["fluid-region-1"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_overset_componen_list.set_state(["no"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_type_list.set_state(["fluid"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_volume_fill_list.set_state(["hexcore"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_leakage_size_list.set_state([""]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_mesh_method_list.set_state(["wrap"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_name_list.set_state(["fluid-region-1"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_overset_componen_list.set_state(["no"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_type_list.set_state(["fluid"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].arguments.all_region_volume_fill_list.set_state(["tet"]) + fault_tolerant.task_object.update_region_settings[ + "Update Region Settings" + ].execute() + + # Choose mesh control options + fault_tolerant.task_object.choose_mesh_control_options[ + "Choose Mesh Control Options" + ].execute() + + # Generate surface mesh + fault_tolerant.task_object.generate_surface_mesh[ + "Generate the Surface Mesh" + ].execute() + + # Update boundaries + fault_tolerant.task_object.update_boundaries["Update Boundaries"].execute() + + # Add boundary layers + fault_tolerant.task_object.add_boundary_layers[ + "Add Boundary Layers" + ].arguments.control_name.set_state("aspect-ratio_1") + fault_tolerant.task_object.add_boundary_layers[ + "Add Boundary Layers" + ].insert_compound_child_task() + fault_tolerant.task_object.add_boundary_layers["aspect-ratio_1"].execute() + + # Generate volume mesh + # fault_tolerant.task_object.create_volume_mesh["Generate the Volume Mesh"].arguments.all_region_name_list.set_state( + # [ + # "main", + # "flow_pipe", + # "outpipe3", + # "object2", + # "object1", + # "void-region-1", + # "fluid-region-1", + # ] + # ) + # fault_tolerant.task_object.create_volume_mesh["Generate the Volume Mesh"].arguments.all_region_size_list.set_state(["11.33375"] * 7) + # fault_tolerant.task_object.create_volume_mesh["Generate the Volume Mesh"].arguments.all_region_volume_fill_list.set_state(["none"] * 6 + ["tet"]) + fault_tolerant.task_object.create_volume_mesh["Generate the Volume Mesh"].execute() + + # Generate volume mesh + solver = meshing.switch_to_solver() + assert solver.is_active() is True + assert meshing.is_active() is False + solver.exit() + assert solver.is_active() is False + + +@pytest.mark.skip +@pytest.mark.fluent_version(">=26.1") +def test_updating_state_in_new_meshing_workflow(new_meshing_session): + # Import geometry + import_file_name = examples.download_file( + "mixing_elbow.pmdb", "pyfluent/mixing_elbow" + ) + new_meshing_session.workflow.InitializeWorkflow(WorkflowType="Watertight Geometry") + watertight = new_meshing_session.meshing_workflow + assert ( + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.length_unit() + == "mm" + ) + assert ( + watertight.task_object.import_geometry[ + "Import Geometry" + ].cad_import_options.feature_angle() + == 40.0 + ) + assert watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.cad_import_options.one_zone_per.allowed_values() == [ + "body", + "face", + "object", + ] + assert ( + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.cad_import_options.one_zone_per() + == "body" + ) + watertight.task_object.import_geometry["Import Geometry"].arguments = { + "file_name": import_file_name, + "length_unit": "in", + "cad_import_options": {"feature_angle": 35, "one_zone_per": "object"}, + } + assert ( + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.cad_import_options.feature_angle() + == 35.0 + ) + assert ( + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.cad_import_options.one_zone_per.get_state() + == "object" + ) + assert ( + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.length_unit.get_state() + == "in" + ) + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.cad_import_options.feature_angle = 25.0 + assert ( + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.cad_import_options.feature_angle() + == 25.0 + ) + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.cad_import_options.one_zone_per = "face" + assert ( + watertight.task_object.import_geometry[ + "Import Geometry" + ].arguments.cad_import_options.one_zone_per() + == "face" + ) + watertight.task_object.import_geometry["Import Geometry"].execute() From d78f01da8dc44343c7d1bc925072405f4bbf4a06 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Tue, 19 Aug 2025 19:47:08 +0530 Subject: [PATCH 09/10] Update test. --- tests/test_server_meshing_workflow.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_server_meshing_workflow.py b/tests/test_server_meshing_workflow.py index 5c6b47e42507..53d7a33795c2 100644 --- a/tests/test_server_meshing_workflow.py +++ b/tests/test_server_meshing_workflow.py @@ -482,7 +482,6 @@ def test_new_fault_tolerant_workflow(new_meshing_session_wo_exit): assert solver.is_active() is False -@pytest.mark.skip @pytest.mark.fluent_version(">=26.1") def test_updating_state_in_new_meshing_workflow(new_meshing_session): # Import geometry From 87f826db9016f9d8bfd78a7343ac639ee786a716 Mon Sep 17 00:00:00 2001 From: Prithwish Mukherjee Date: Wed, 20 Aug 2025 13:14:46 +0530 Subject: [PATCH 10/10] Add 2d workflow test. --- tests/test_server_meshing_workflow.py | 201 +++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 1 deletion(-) diff --git a/tests/test_server_meshing_workflow.py b/tests/test_server_meshing_workflow.py index 53d7a33795c2..6d3a7fe56488 100644 --- a/tests/test_server_meshing_workflow.py +++ b/tests/test_server_meshing_workflow.py @@ -132,6 +132,7 @@ def test_new_watertight_workflow(new_meshing_session_wo_exit): assert solver.is_active() is False +@pytest.mark.fluent_version(">=26.1") def test_new_fault_tolerant_workflow(new_meshing_session_wo_exit): meshing = new_meshing_session_wo_exit @@ -482,6 +483,204 @@ def test_new_fault_tolerant_workflow(new_meshing_session_wo_exit): assert solver.is_active() is False +@pytest.mark.fluent_version(">=26.1") +def test_new_2d_meshing_workflow(new_meshing_session_wo_exit): + # Import geometry + import_file_name = examples.download_file("NACA0012.fmd", "pyfluent/airfoils") + new_meshing_session_wo_exit.workflow.InitializeWorkflow(WorkflowType="2D Meshing") + + two_dim_mesh = new_meshing_session_wo_exit.meshing_workflow + + two_dim_mesh.task_object.load_cad_geometry[ + "Load CAD Geometry" + ].arguments.file_name = import_file_name + two_dim_mesh.task_object.load_cad_geometry[ + "Load CAD Geometry" + ].arguments.length_unit = "mm" + two_dim_mesh.task_object.load_cad_geometry[ + "Load CAD Geometry" + ].arguments.refaceting.refacet = False + two_dim_mesh.task_object.load_cad_geometry["Load CAD Geometry"].execute() + + # Set regions and boundaries + two_dim_mesh.task_object.update_boundaries[ + "Update Boundaries" + ].arguments.selection_type = "zone" + two_dim_mesh.task_object.update_boundaries["Update Boundaries"].execute() + + # Define global sizing + two_dim_mesh.task_object.define_global_sizing[ + "Define Global Sizing" + ].arguments.curvature_normal_angle = 20 + two_dim_mesh.task_object.define_global_sizing[ + "Define Global Sizing" + ].arguments.max_size = 2000.0 + two_dim_mesh.task_object.define_global_sizing[ + "Define Global Sizing" + ].arguments.min_size = 5.0 + two_dim_mesh.task_object.define_global_sizing[ + "Define Global Sizing" + ].arguments.size_functions = "Curvature" + two_dim_mesh.task_object.define_global_sizing["Define Global Sizing"].execute() + + # Add local sizing + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.add_child = True + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_control_name = "boi_1" + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_execution = "Body Of Influence" + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_face_label_list = ["boi"] + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_size = 50.0 + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_zoneor_label = "label" + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.draw_size_control = True + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].add_child_and_update(defer_update=False) + + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.add_child = True + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_control_name = "edgesize_1" + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_execution = "Edge Size" + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_size = 5.0 + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_zoneor_label = "label" + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.draw_size_control = True + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.edge_label_list = ["airfoil-te"] + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.add_child_and_update(defer_update=False) + + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.add_child = True + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_control_name = "curvature_1" + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_curvature_normal_angle = 10 + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_execution = "Curvature" + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_max_size = 2 + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_min_size = 1.5 + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_scope_to = "edges" + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.boi_zoneor_label = "label" + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.draw_size_control = True + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].arguments.edge_label_list = ["airfoil"] + two_dim_mesh.task_object.add_local_sizing_wtm[ + "Add Local Sizing" + ].add_child_and_update(defer_update=False) + + # Add boundary layer + two_dim_mesh.task_object.add_2d_boundary_layers[ + "Add 2D Boundary Layers" + ].arguments.add_child = True + two_dim_mesh.task_object.add_2d_boundary_layers[ + "Add 2D Boundary Layers" + ].arguments.control_name = "aspect-ratio_1" + two_dim_mesh.task_object.add_2d_boundary_layers[ + "Add 2D Boundary Layers" + ].arguments.number_of_layers = 4 + two_dim_mesh.task_object.add_2d_boundary_layers[ + "Add 2D Boundary Layers" + ].arguments.offset_method_type = "aspect-ratio" + two_dim_mesh.task_object.add_2d_boundary_layers[ + "Add 2D Boundary Layers" + ].add_child_and_update(defer_update=False) + + # NOTE: Setting `show_advanced_options = True` is required to configure advanced preferences. + # This dependency may be removed in a future release as the API evolves. + two_dim_mesh.task_object.generate_initial_surface_mesh[ + "Generate the Surface Mesh" + ].arguments.surface_2d_preferences.show_advanced_options = True + two_dim_mesh.task_object.generate_initial_surface_mesh[ + "Generate the Surface Mesh" + ].arguments.surface_2d_preferences.merge_edge_zones_based_on_labels = False + two_dim_mesh.task_object.generate_initial_surface_mesh[ + "Generate the Surface Mesh" + ].arguments.surface_2d_preferences.merge_face_zones_based_on_labels = False + two_dim_mesh.task_object.generate_initial_surface_mesh[ + "Generate the Surface Mesh" + ].execute() + + two_dim_mesh.task_object.add_2d_boundary_layers["Add 2D Boundary Layers"].revert() + two_dim_mesh.task_object.add_2d_boundary_layers[ + "Add 2D Boundary Layers" + ].arguments.add_child = "yes" + two_dim_mesh.task_object.add_2d_boundary_layers[ + "Add 2D Boundary Layers" + ].arguments.control_name = "uniform_1" + two_dim_mesh.task_object.add_2d_boundary_layers[ + "Add 2D Boundary Layers" + ].arguments.first_layer_height = 2 + two_dim_mesh.task_object.add_2d_boundary_layers[ + "Add 2D Boundary Layers" + ].arguments.number_of_layers = 4 + two_dim_mesh.task_object.add_2d_boundary_layers[ + "Add 2D Boundary Layers" + ].arguments.offset_method_type = "uniform" + two_dim_mesh.task_object.add_2d_boundary_layers["Add 2D Boundary Layers"].execute() + + # NOTE: Setting `show_advanced_options = True` is required to configure advanced preferences. + # This dependency may be removed in a future release as the API evolves. + two_dim_mesh.task_object.generate_initial_surface_mesh[ + "Generate the Surface Mesh" + ].arguments.surface_2d_preferences.show_advanced_options = True + two_dim_mesh.task_object.generate_initial_surface_mesh[ + "Generate the Surface Mesh" + ].arguments.surface_2d_preferences.merge_edge_zones_based_on_labels = False + two_dim_mesh.task_object.generate_initial_surface_mesh[ + "Generate the Surface Mesh" + ].arguments.surface_2d_preferences.merge_face_zones_based_on_labels = False + two_dim_mesh.task_object.generate_initial_surface_mesh[ + "Generate the Surface Mesh" + ].execute() + + # Switch to solution mode + solver = new_meshing_session_wo_exit.switch_to_solver() + assert solver.is_active() is True + assert new_meshing_session_wo_exit.is_active() is False + solver.exit() + assert solver.is_active() is False + + @pytest.mark.fluent_version(">=26.1") def test_updating_state_in_new_meshing_workflow(new_meshing_session): # Import geometry @@ -499,7 +698,7 @@ def test_updating_state_in_new_meshing_workflow(new_meshing_session): assert ( watertight.task_object.import_geometry[ "Import Geometry" - ].cad_import_options.feature_angle() + ].arguments.cad_import_options.feature_angle() == 40.0 ) assert watertight.task_object.import_geometry[