Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
fc8c72b
refactor: added the changes
mayankansys Mar 12, 2026
f94faa6
chore: adding changelog file 4990.miscellaneous.md [dependabot-skip]
pyansys-ci-bot Mar 12, 2026
25a3143
update
mayankansys Mar 17, 2026
2065946
Merge branch 'main' into refactor/couple_issues_launch_fluent
mayankansys Mar 17, 2026
c359acd
Merge branch 'refactor/couple_issues_launch_fluent' of https://github…
mayankansys Mar 17, 2026
9aea156
Merge branch 'main' into refactor/couple_issues_launch_fluent
mayankansys Mar 18, 2026
481f46f
Merge branch 'main' into refactor/couple_issues_launch_fluent
mayankansys Mar 20, 2026
8d64547
Merge branch 'main' into refactor/couple_issues_launch_fluent
mayankansys Mar 25, 2026
ae8f3cc
Merge branch 'main' into refactor/couple_issues_launch_fluent
mayankansys Apr 1, 2026
bf31ed6
Merge branch 'refactor/couple_issues_launch_fluent' of https://github…
mayankansys Jun 5, 2026
26d259f
updated the standalone_launcher
mayankansys Jun 16, 2026
bbcd2fd
resolved the conflict
mayankansys Jun 17, 2026
482b20f
update
mayankansys Mar 17, 2026
7c5fd0c
chore: adding changelog file 4990.miscellaneous.md [dependabot-skip]
pyansys-ci-bot Mar 12, 2026
b74d226
updated the standalone_launcher
mayankansys Jun 16, 2026
5ec458e
resolved the conflict
mayankansys Jun 17, 2026
28135e9
Merge branch 'main' into refactor/couple_issues_launch_fluent
mayankansys Jun 17, 2026
98945db
Merge branch 'main' into refactor/couple_issues_launch_fluent
mayankansys Jun 22, 2026
1bc029c
standalone launcher updated for the lightweight_mode, case_file and j…
mayankansys Jun 22, 2026
3563a14
Merge branch 'refactor/couple_issues_launch_fluent' of https://github…
mayankansys Jun 22, 2026
0a2861f
updated the condition logic & minor things
mayankansys Jun 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/changelog.d/4265.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Fixed `launch_fluent()` ordering so `case_file_name`/`case_data_file_name` are processed before `journal_file_names` when both are provided.
- In lightweight mode, deferred journal replay now completes before the background sync step begins.
1 change: 1 addition & 0 deletions doc/changelog.d/4990.miscellaneous.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Couple of issues in launch fluent
12 changes: 8 additions & 4 deletions src/ansys/fluent/core/launcher/launcher_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,16 @@ def _confirm_watchdog_start(start_watchdog, cleanup_on_exit, fluent_connection):


def _build_journal_argument(
topy: None | bool | str, journal_file_names: None | str | list[str]
topy: None | bool | str,
journal_file_names: None | str | list[str],
include_journal_file_names: bool = True,
) -> str:
"""Build Fluent commandline journal argument."""

def _impl(
topy: None | bool | str, journal_file_names: None | str | list[str]
topy: None | bool | str,
journal_file_names: None | str | list[str],
include_journal_file_names: bool,
) -> str:
if journal_file_names and not isinstance(journal_file_names, (str, list)):
raise TypeError(
Expand All @@ -228,7 +232,7 @@ def _impl(
fluent_jou_arg = ""
if isinstance(journal_file_names, str):
journal_file_names = [journal_file_names]
if journal_file_names:
if journal_file_names and include_journal_file_names:
fluent_jou_arg += "".join(
[f' -i "{journal}"' for journal in journal_file_names]
)
Expand All @@ -239,4 +243,4 @@ def _impl(
fluent_jou_arg += " -topy"
return fluent_jou_arg

return _impl(topy, journal_file_names)
return _impl(topy, journal_file_names, include_journal_file_names)
106 changes: 72 additions & 34 deletions src/ansys/fluent/core/launcher/standalone_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
from pathlib import Path
import subprocess
from typing import TYPE_CHECKING, Any, TypedDict
import warnings

from typing_extensions import Unpack

Expand All @@ -67,6 +68,7 @@
_get_server_info_file_names,
)
import ansys.fluent.core.launcher.watchdog as watchdog
from ansys.fluent.core.pyfluent_warnings import PyFluentUserWarning
from ansys.fluent.core.utils.fluent_version import FluentVersion

if TYPE_CHECKING:
Expand Down Expand Up @@ -188,6 +190,8 @@ def __init__(
lightweight_mode : bool, optional
If True, runs in lightweight mode where mesh settings are read into a background solver session,
replacing it once complete. This parameter is only applicable when `case_file_name` is provided; defaults to False.
When combined with `journal_file_names`, a warning is issued and `lightweight_mode` is set to False, as
journal processing cannot be reliably ordered with mesh-only initialization.
py : bool, optional
If True, runs Fluent in Python mode. Defaults to None.
gpu : bool, optional
Expand All @@ -214,6 +218,10 @@ def __init__(
-----
In job scheduler environments (e.g., SLURM, LSF, PBS), resources and compute nodes are allocated,
and core counts are queried from these environments before being passed to Fluent.

File processing order: Case files are processed before case-data files, which are processed before
journal files. In lightweight mode, journal files are read before the background session is synchronized
with the foreground session.
"""
import ansys.fluent.core as pyfluent

Expand All @@ -224,6 +232,15 @@ def __init__(
self.argvals["ui_mode"] = UIMode(kwargs.get("ui_mode"))
if self.argvals.get("lightweight_mode") is None:
self.argvals["lightweight_mode"] = False

if self.argvals["lightweight_mode"] and self.argvals.get("journal_file_names"):
warnings.warn(
"'lightweight_mode' is not supported together with "
"'journal_file_names' and will be ignored.",
PyFluentUserWarning,
)
self.argvals["lightweight_mode"] = False

fluent_version = _get_standalone_launch_fluent_version(self.argvals)

if (
Expand Down Expand Up @@ -255,11 +272,14 @@ def __init__(
self._kwargs = _get_subprocess_kwargs_for_fluent(
self.argvals.get("env") or {}, self.argvals
)
if self.argvals.get("cwd"):
self._kwargs.update(cwd=self.argvals.get("cwd"))
self._launch_string += _build_journal_argument(
self.argvals.get("topy", []), self.argvals.get("journal_file_names")
)
if self.argvals["cwd"]:
self._kwargs.update(cwd=self.argvals["cwd"])

topy = self.argvals.get("topy", [])
if topy:
self._launch_string += _build_journal_argument(
topy, self.argvals.get("journal_file_names")
)

if is_windows():
self._launch_cmd = self._launch_string
Expand Down Expand Up @@ -344,35 +364,8 @@ def __call__(
values = _get_server_info(self._server_info_file_name)
if len(values) == 3:
ip, port, password = values
watchdog.launch(
os.getpid(),
port,
password,
ip,
inside_container=False,
)
# PyFluent is now connected: disable the idle-timeout guard.
self._disable_idle_timeout_guard(session)
if self.argvals.get("case_file_name"):
if FluentMode.is_meshing(self.argvals.get("mode")):
session.tui.file.read_case(self.argvals.get("case_file_name"))
elif self.argvals.get("lightweight_mode"):
session.read_case_lightweight(self.argvals.get("case_file_name"))
else:
session.settings.file.read(
file_type="case",
file_name=self.argvals.get("case_file_name"),
)
if self.argvals.get("case_data_file_name"):
if not FluentMode.is_meshing(self.argvals.get("mode")):
session.settings.file.read(
file_type="case-data",
file_name=self.argvals.get("case_data_file_name"),
)
else:
raise RuntimeError(
"Case and data file cannot be read in meshing mode."
)
watchdog.launch(os.getpid(), port, password, ip)
self._process_case_data_and_journals(session)

return session
except Exception as ex:
Expand All @@ -382,3 +375,48 @@ def __call__(
server_info_file = Path(self._server_info_file_name)
if server_info_file.exists():
server_info_file.unlink()

@staticmethod
def _get_journal_file_names(
journal_file_names: None | str | list[str],
) -> list[str]:
if isinstance(journal_file_names, str):
return [journal_file_names]
return journal_file_names or []

def _process_case_data_and_journals(self, session) -> None:
if self.argvals["case_file_name"]:
if FluentMode.is_meshing(self.argvals["mode"]):
session.tui.file.read_case(self.argvals["case_file_name"])
elif self.argvals["lightweight_mode"]:
session.read_case_lightweight(
self.argvals["case_file_name"],
start_sync=False,
)
else:
session.settings.file.read(
file_type="case",
file_name=self.argvals["case_file_name"],
)
if self.argvals["case_data_file_name"]:
if not FluentMode.is_meshing(self.argvals["mode"]):
session.settings.file.read(
file_type="case-data",
file_name=self.argvals["case_data_file_name"],
)
else:
raise RuntimeError("Case and data file cannot be read in meshing mode.")

if self.argvals.get("topy"):
for journal_file_name in self._get_journal_file_names(
self.argvals.get("journal_file_names")
):
session.tui.file.write_journal(f"{journal_file_name}.topy")
else:
for journal_file_name in self._get_journal_file_names(
self.argvals.get("journal_file_names")
):
session.execute_tui(f'/file/read-journal "{journal_file_name}"')

if self.argvals.get("lightweight_mode"):
session.start_case_lightweight_sync()
12 changes: 11 additions & 1 deletion src/ansys/fluent/core/session_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,13 +385,21 @@ def _stop_bg_sessions(self):
if thread.is_alive():
thread.join()

def read_case_lightweight(self, file_name: str):
def start_case_lightweight_sync(self):
"""Start pending lightweight background sync sessions."""
for thread in self._bg_session_threads:
if thread.ident is None:
thread.start()

def read_case_lightweight(self, file_name: str, start_sync: bool = True):
"""Read a case file using light IO mode.

Parameters
----------
file_name : str
Case file name
start_sync : bool, optional
Whether to immediately start lightweight background sync.
"""

self.settings.file.read(
Expand All @@ -405,6 +413,8 @@ def read_case_lightweight(self, file_name: str):
target=self._start_bg_session_and_sync, args=(launcher_args,)
)
)
if start_sync:
self.start_case_lightweight_sync()

def get_state(self) -> StateT:
"""Get the state of the object."""
Expand Down
77 changes: 77 additions & 0 deletions tests/test_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
_build_fluent_launch_args_string,
get_fluent_exe_path,
)
from ansys.fluent.core.launcher.standalone_launcher import StandaloneLauncher
from ansys.fluent.core.utils.fluent_version import FluentVersion
import ansys.platform.instancemanagement as pypim

Expand Down Expand Up @@ -473,6 +474,82 @@ def test_build_journal_argument(topy, journal_file_names, result, raises):
assert _build_journal_argument(topy, journal_file_names) == result


def test_build_journal_argument_without_journal_files_but_with_topy():
assert (
_build_journal_argument("a.py", ["a.jou"], include_journal_file_names=False)
== ' -topy="a.py"'
)


def test_lightweight_case_journal_read_is_completed_before_sync_step():
launcher = object.__new__(StandaloneLauncher)
launcher.argvals = {
"case_file_name": "a.cas.h5",
"case_data_file_name": None,
"mode": FluentMode.SOLVER,
"lightweight_mode": True,
"journal_file_names": ["a.jou", "b.jou"],
}
launcher._defer_journal_file_read = True

calls = []

class _DummySession:
def read_case_lightweight(self, file_name, start_sync=True):
calls.append(("read_case_lightweight", file_name, start_sync))

def execute_tui(self, command):
calls.append(("execute_tui", command))

def start_case_lightweight_sync(self):
calls.append(("start_case_lightweight_sync",))

launcher._process_case_data_and_journals(_DummySession())

assert calls == [
("read_case_lightweight", "a.cas.h5", False),
("execute_tui", '/file/read-journal "a.jou"'),
("execute_tui", '/file/read-journal "b.jou"'),
("start_case_lightweight_sync",),
]


def test_case_and_case_data_are_processed_before_journal_files():
launcher = object.__new__(StandaloneLauncher)
launcher.argvals = {
"case_file_name": "a.cas.h5",
"case_data_file_name": "a.cas.h5",
"mode": FluentMode.SOLVER,
"lightweight_mode": False,
"journal_file_names": ["a.jou", "b.jou"],
}
launcher._defer_journal_file_read = True

calls = []

class _DummyFile:
def read(self, **kwargs):
calls.append(("read", kwargs))

class _DummySettings:
file = _DummyFile()

class _DummySession:
settings = _DummySettings()

def execute_tui(self, command):
calls.append(("execute_tui", command))

launcher._process_case_data_and_journals(_DummySession())

assert calls == [
("read", {"file_type": "case", "file_name": "a.cas.h5"}),
("read", {"file_type": "case-data", "file_name": "a.cas.h5"}),
("execute_tui", '/file/read-journal "a.jou"'),
("execute_tui", '/file/read-journal "b.jou"'),
]


def test_show_gui_raises_warning():
with pytest.warns(PyFluentDeprecationWarning):
grpc_kwds = get_grpc_launcher_args_for_gh_runs()
Expand Down
Loading