Skip to content

Commit

Permalink
feat: wf speed (#3210)
Browse files Browse the repository at this point in the history
* move call out of loop

* wotnot

* wotnot

* further optimise

* Update src/ansys/fluent/core/workflow.py

* Separate out classic meshing interface.

* Add 'mark_as_updated'.

* Update workflow access.

* Update tests.

* Fix and update tests.

* Fix test.

* Update docs.

* Fix test.

* Clean up __getattr__

* Update documentation.

* Update doc/source/user_guide/meshing/new_meshing_workflows.rst

Co-authored-by: Kathy Pippert <[email protected]>

* Update doc/source/user_guide/meshing/new_meshing_workflows.rst

* Update doc/source/user_guide/meshing/new_meshing_workflows.rst

* Update doc/source/user_guide/meshing/new_meshing_workflows.rst

Co-authored-by: Kathy Pippert <[email protected]>

* Update doc/source/user_guide/meshing/new_meshing_workflows.rst

Co-authored-by: Kathy Pippert <[email protected]>

* Update src/ansys/fluent/core/session.py

Co-authored-by: Kathy Pippert <[email protected]>

* Update src/ansys/fluent/core/workflow.py

Co-authored-by: Kathy Pippert <[email protected]>

* ci: auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: Prithwish Mukherjee <[email protected]>
Co-authored-by: Prithwish Mukherjee <[email protected]>
Co-authored-by: Kathy Pippert <[email protected]>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
5 people authored Aug 23, 2024
1 parent 2398bc3 commit e2d89e3
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 251 deletions.
37 changes: 2 additions & 35 deletions doc/source/user_guide/meshing/meshing_workflows.rst
Original file line number Diff line number Diff line change
Expand Up @@ -830,39 +830,6 @@ Switch to solver mode
Switching to solver mode is not allowed in 2D Meshing mode.


Sample use of ``CommandArguments``
----------------------------------
This simple example shows how to use the ``CommandArgument`` attributes and explicit
attribute access methods in a watertight geometry meshing workflow.

.. Note::
``CommandArgument`` attributes are read-only.

.. code:: python
>>> import ansys.fluent.core as pyfluent
>>> from ansys.fluent.core import examples
>>> import_file_name = examples.download_file("mixing_elbow.pmdb", "pyfluent/mixing_elbow")
>>> meshing = pyfluent.launch_fluent(
>>> mode=pyfluent.FluentMode.MESHING,
>>> precision=pyfluent.Precision.DOUBLE,
>>> processor_count=2
>>> )
>>> workflow = meshing.workflow
>>> workflow.InitializeWorkflow(WorkflowType="Watertight Geometry")
>>> tasks = workflow.TaskObject
>>> import_geometry = tasks["Import Geometry"]
>>> import_geometry.CommandArguments()
>>> import_geometry.CommandArguments.FileName.is_read_only()
>>> import_geometry.CommandArguments.LengthUnit.is_active()
>>> import_geometry.CommandArguments.LengthUnit.allowed_values()
>>> import_geometry.CommandArguments.LengthUnit.default_value()
>>> import_geometry.CommandArguments.LengthUnit()
>>> import_geometry.CommandArguments.CadImportOptions.OneZonePer()
>>> import_geometry.CommandArguments.CadImportOptions.FeatureAngle.min()
State access
------------
You can call the ``TaskObject`` container to get its state:
Expand All @@ -875,5 +842,5 @@ The ``TaskObject`` container supports dictionary semantics:

.. code:: python
>>> for name, object in meshing.workflow.TaskObject.items():
>>> print(f"Task name: {name}, state: {object()}")
>>> for name, object_dict in meshing.workflow.TaskObject.items():
>>> print(f"Task name: {name}, state: {object_dict}")
57 changes: 57 additions & 0 deletions doc/source/user_guide/meshing/new_meshing_workflows.rst
Original file line number Diff line number Diff line change
Expand Up @@ -699,3 +699,60 @@ Duplicate tasks
watertight.import_geometry.insertable_tasks.import_boi_geometry.insert()
assert watertight.import_boi_geometry.arguments()
assert watertight.import_boi_geometry_1.arguments()
Current meshing workflow
------------------------
Use the ``current_workflow`` property to access an already loaded workflow.
The following example shows how to use this method.

Current workflow
~~~~~~~~~~~~~~~~

.. code:: python
meshing.current_workflow
.. Note::
The ``current_workflow`` property raises an attribute error when no workflow is initialized.


Mark as updated
---------------
Use the ``mark_as_updated()`` method to forcefully mark a task as updated.

.. code:: python
watertight.import_geometry.mark_as_updated()
Sample use of ``arguments``
----------------------------
This simple example shows how to use the ``arguments`` attributes and explicit
attribute access methods in a watertight geometry meshing workflow.

.. Note::
The ``command_arguments()`` method is deprecated.

.. code:: python
>>> import ansys.fluent.core as pyfluent
>>> from ansys.fluent.core import examples
>>> import_file_name = examples.download_file("mixing_elbow.pmdb", "pyfluent/mixing_elbow")
>>> meshing = pyfluent.launch_fluent(
>>> mode=pyfluent.FluentMode.MESHING,
>>> precision=pyfluent.Precision.DOUBLE,
>>> processor_count=2
>>> )
>>> watertight = meshing.watertight()
>>> import_geometry = watertight.import_geometry
>>> import_geometry.arguments()
>>> import_geometry.arguments.file_name.is_read_only()
>>> import_geometry.arguments.length_unit.is_active()
>>> import_geometry.arguments.length_unit.allowed_values()
>>> import_geometry.arguments.length_unit.default_value()
>>> import_geometry.arguments.length_unit()
>>> import_geometry.arguments.cad_import_options.one_zone_per()
>>> import_geometry.arguments.cad_import_options.feature_angle.min()
4 changes: 3 additions & 1 deletion src/ansys/fluent/core/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ def __call__(self):


class BaseSession:
"""Instantiates a Fluent connection.
"""Encapsulates a Fluent session.
This class exposes methods for interacting with a Fluent session.
Attributes
----------
Expand Down
80 changes: 41 additions & 39 deletions src/ansys/fluent/core/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,12 @@ def get_direct_downstream_tasks(self) -> list:
attr="outputs", other_attr="requiredInputs"
)

def mark_as_updated(self) -> None:
"""Mark tasks in workflow as updated."""
state = getattr(self, "state", None)
if state and "Forced-up-to-date" in state.allowed_values():
state.set_state("Forced-up-to-date")

def tasks(self, recompute=True) -> list:
"""Get the ordered task list held by this task.
Expand Down Expand Up @@ -419,6 +425,9 @@ def _get_camel_case_arg_keys(self):
return camel_args

def __getattr__(self, attr):
result = getattr(self._task, attr, None)
if result:
return result
if self._dynamic_interface:
if not attr.islower() and attr != "Arguments":
raise AttributeError(
Expand All @@ -433,12 +442,9 @@ def __getattr__(self, attr):
else attr
)
attr = camel_attr or attr
try:
result = getattr(self._task, attr)
if result:
return result
except AttributeError:
pass
result = getattr(self._task, attr, None)
if result:
return result
try:
return ArgumentWrapper(self, attr)
except Exception as ex:
Expand Down Expand Up @@ -659,7 +665,7 @@ def __iter__(self) -> Iterator[BaseTask]:

def __getitem__(self, name):
logger.debug(f"TaskContainer.__getitem__({name})")
return _makeTask(self._container, name)
return self._container._workflow.TaskObject[name]

def __getattr__(self, attr):
return getattr(self._task_container, attr)
Expand Down Expand Up @@ -732,12 +738,13 @@ def update_dict(self, args: dict) -> None:
"""
self._assign(args, "update_dict")

def _camel_snake_arguments_map(self, input_dict):
def _camel_snake_arguments_map(self, input_dict, cmd_args=None):
snake_case_state_dict = {}
cmd_args = self._task._command_arguments if cmd_args is None else cmd_args
for key, val in input_dict.items():
self._snake_to_camel_map[camel_to_snake_case(key)] = key
if isinstance(
getattr(self._task._command_arguments, key),
getattr(cmd_args, key),
PySingletonCommandArgumentsSubItem,
):
snake_case_state_dict[camel_to_snake_case(key)] = (
Expand Down Expand Up @@ -823,6 +830,8 @@ def _just_set_state(self, args):
self._task.Arguments.set_state(args)

def __getattr__(self, attr):
if self._dynamic_interface:
return getattr(self._task, attr)
return getattr(self._task._command_arguments, attr)

def __setattr__(self, key, value):
Expand All @@ -834,7 +843,15 @@ def __setattr__(self, key, value):
)

def __setitem__(self, key, value):
self._task._command_arguments.__setitem__(key, value)
if self._dynamic_interface:
getattr(self._task, key).set_state(value)
else:
self._task._command_arguments.__setitem__(key, value)

def __getitem__(self, item):
if self._dynamic_interface:
return getattr(self._task, item).get_state()
return self._task._command_arguments.__getitem__(item)


class ArgumentWrapper(PyCallableStateObject):
Expand Down Expand Up @@ -898,6 +915,8 @@ def get_state(self, explicit_only: bool = False) -> Any:
return state_dict

def _get_camel_case_arg_keys(self):
if not isinstance(self(), dict):
return
_args = self
_camel_args = []
for arg in _args().keys():
Expand All @@ -915,7 +934,9 @@ def __getattr__(self, attr):
"Camel case attribute access is not supported. "
f"Try using '{camel_to_snake_case(attr)}' instead."
)
camel_attr = snake_to_camel_case(str(attr), self._get_camel_case_arg_keys())
camel_attr = snake_to_camel_case(
str(attr), self._get_camel_case_arg_keys() or []
)
attr = camel_attr or attr
return getattr(self._arg, attr)

Expand All @@ -925,7 +946,7 @@ def __setattr__(self, attr, value):
else:
if self._dynamic_interface:
camel_attr = snake_to_camel_case(
str(attr), self._get_camel_case_arg_keys()
str(attr), self._get_camel_case_arg_keys() or []
)
attr = camel_attr or attr
self.set_state({attr: value})
Expand Down Expand Up @@ -1259,7 +1280,6 @@ def compound_child(self, name: str):
def _makeTask(command_source, name: str) -> BaseTask:
task = command_source._workflow.TaskObject[name]
kinds = {
None: BaseTask, # To support old fluent journals setting empty state to Task Objects
"Simple": SimpleTask,
"Compound Child": CompoundChild,
"Compound": CompoundTask,
Expand Down Expand Up @@ -1432,9 +1452,10 @@ def __getattr__(self, attr):
)
camel_attr = snake_to_camel_case(str(attr), dir(self._workflow))
attr = camel_attr or attr
obj = self._attr_from_wrapped_workflow(attr)
if obj:
return obj
try:
return getattr(self._workflow, attr)
except AttributeError:
pass
return super().__getattribute__(attr)

def __setattr__(self, attr, value):
Expand Down Expand Up @@ -1485,14 +1506,6 @@ def _task_by_id(self, task_id):
workflow_state = self._workflow_state()
return self._task_by_id_impl(task_id, workflow_state)

def _attr_from_wrapped_workflow(self, attr):
try:
result = getattr(self._workflow, attr)
if result:
return result
except AttributeError:
pass

def _activate_dynamic_interface(self, dynamic_interface: bool):
self._dynamic_interface = dynamic_interface
self._initialize_methods(dynamic_interface=dynamic_interface)
Expand Down Expand Up @@ -1688,12 +1701,9 @@ def TaskObject(self) -> TaskContainer:

def __getattr__(self, attr):
"""Delegate attribute lookup to the wrapped workflow object."""
obj = self._attr_from_wrapped_workflow(
attr
) # or self._task_with_cmd_matching_help_string(attr)
if obj:
return obj
else:
try:
return getattr(self._workflow, attr)
except AttributeError:
return super().__getattribute__(attr)

def __dir__(self):
Expand All @@ -1707,17 +1717,9 @@ def __call__(self):
"""Delegate calls to the underlying workflow."""
return self._workflow()

def _attr_from_wrapped_workflow(self, attr):
try:
result = getattr(self._workflow, attr)
if result:
return result
except AttributeError:
pass


class ReadOnlyObject:
"""Removes set_state() to implement read-only behaviour."""
"""Removes ``set_state()`` to implement read-only behavior."""

_unwanted_attr = ["set_state", "setState"]

Expand Down
8 changes: 4 additions & 4 deletions tests/test_data_model_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,15 @@ def test_update_cache_internal_names_as_keys(
assert cache_rules == final_cache


@pytest.mark.fluent_version(">=23.1")
@pytest.mark.fluent_version(">=23.2")
@pytest.mark.codegen_required
def test_get_cached_values_in_command_arguments(new_meshing_session):
new_meshing_session.workflow.InitializeWorkflow(WorkflowType="Watertight Geometry")
wt = new_meshing_session.watertight()
geo_import = new_meshing_session.workflow.TaskObject["Import Geometry"]
geo_import.Arguments = dict(FileName="Bob")
geo_import.Arguments = dict(FileName=None)
assert "FileName" in geo_import.command_arguments()
assert geo_import.command_arguments()["FileName"] is None
assert "FileName" in wt.import_geometry.command_arguments()
assert wt.import_geometry.command_arguments()["FileName"] is None


@pytest.fixture
Expand Down
6 changes: 3 additions & 3 deletions tests/test_datamodel_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ def test_add_on_affected(new_meshing_session):
lambda obj: data.append(True)
)
assert data == []
meshing.workflow.InitializeWorkflow(WorkflowType="Watertight Geometry")
wt = meshing.watertight()
sleep(5)
assert len(data) > 0
assert data[0] == True
Expand All @@ -175,10 +175,10 @@ def test_add_on_affected(new_meshing_session):
)
import_geom = meshing.workflow.TaskObject["Import Geometry"]
assert "FileName" not in import_geom.Arguments()
assert import_geom.command_arguments()["FileName"] is None
assert wt.import_geometry.command_arguments()["FileName"] is None
import_geom.Arguments = {"FileName": geom}
assert import_geom.Arguments()["FileName"] == geom
assert import_geom.command_arguments()["FileName"] == geom
assert wt.import_geometry.command_arguments()["FileName"] == geom
sleep(1)
assert calls == [True]
import_geom.Arguments = {"FileName": "dummy"}
Expand Down
1 change: 1 addition & 0 deletions tests/test_meshing_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ def pytest_approx(expected):
return pytest.approx(expected=expected, rel=PYTEST_RELATIVE_TOLERANCE)


@pytest.mark.skip("Activate with: https://github.com/ansys/pyfluent/pull/3205")
@pytest.mark.codegen_required
@pytest.mark.nightly
@pytest.mark.fluent_version(">=25.1")
Expand Down
Loading

0 comments on commit e2d89e3

Please sign in to comment.