Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Return launch and connection info from standalone launcher dry-run #3576

Merged
merged 8 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
5 changes: 3 additions & 2 deletions src/ansys/fluent/core/launcher/launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,9 @@ def launch_fluent(
See also :mod:`~ansys.fluent.core.launcher.fluent_container`.
dry_run : bool, optional
Defaults to False. If True, will not launch Fluent, and will instead print configuration information
that would be used as if Fluent was being launched. If dry running a container start,
``launch_fluent()`` will return the configured ``container_dict``.
that would be used as if Fluent was being launched. If dry running a standalone start
``launch_fluent()`` will return a tuple containing Fluent launch string and the server info file name.
If dry running a container start, ``launch_fluent()`` will return the configured ``container_dict``.
cleanup_on_exit : bool, optional
Whether to shut down the connected Fluent session when PyFluent is
exited, or the ``exit()`` method is called on the session instance,
Expand Down
14 changes: 8 additions & 6 deletions src/ansys/fluent/core/launcher/process_launch_string.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,14 @@ def get_exe_path(fluent_root: Path) -> Path:
return fluent_root / "bin" / "fluent"

# Look for Fluent exe path in the following order:
# 1. product_version parameter passed with launch_fluent
# 1. Custom Path provided by the user in launch_fluent
mkundu1 marked this conversation as resolved.
Show resolved Hide resolved
fluent_path = launch_argvals.get("fluent_path")
if fluent_path:
# Return the fluent_path string verbatim. The path may not even exist
# in the current machine if user wants to launch fluent externally (dry_run use case).
return fluent_path

# 2. product_version parameter passed with launch_fluent
product_version = launch_argvals.get("product_version")
if product_version:
return get_exe_path(get_fluent_root(FluentVersion(product_version)))
Expand All @@ -147,10 +154,5 @@ def get_exe_path(fluent_root: Path) -> Path:
if fluent_root:
return get_exe_path(Path(fluent_root))

# 2. Custom Path provided by the user in launch_fluent
fluent_path = launch_argvals.get("fluent_path")
if fluent_path:
return Path(fluent_path)

# 3. the latest ANSYS version from AWP_ROOT environment variables
return get_exe_path(get_fluent_root(FluentVersion.get_latest_installed()))
27 changes: 25 additions & 2 deletions src/ansys/fluent/core/launcher/server_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,27 @@
from ansys.fluent.core.session import _parse_server_info_file


def _get_server_info_file_name(use_tmpdir=True):
def _get_server_info_file_name(use_tmpdir=True) -> tuple[str, str]:
"""Get a tuple containing server and client-side file names with the server connection information.
When server and client are in a different machine, the environment variable SERVER_INFO_DIR
can be set to a shared directory between the two machines and the server-info file will be
created in that directory. The value of the environment variable SERVER_INFO_DIR can be
different for the server and client machines. The relative path of the server-side server-info
file is passed to Fluent launcher and PyFluent connects to the server using the absolute path
of the client-side server-info file. A typical use case of the environment variable
SERVER_INFO_DIR is as follows:
- Server machine environment variable: SERVER_INFO_DIR=/mnt/shared
- Client machine environment variable: SERVER_INFO_DIR=\\\\server\\shared
- Server-side server-info file: /mnt/shared/serverinfo-xyz.txt
- Client-side server-info file: \\\\server\\shared\\serverinfo-xyz.txt
- Fluent launcher command: fluent ... -sifile=serverinfo-xyz.txt ...
- From PyFluent: connect_to_fluent(server_info_file_name="\\\\server\\shared\\serverinfo-xyz.txt")

When the environment variable SERVER_INFO_DIR is not set, the server-side and client-side
file paths for the server-info file are identical. The server-info file is created in the
temporary directory if ``use_tmpdir`` is True, otherwise it is created in the current working
directory.
"""
server_info_dir = os.getenv("SERVER_INFO_DIR")
dir_ = (
Path(server_info_dir)
Expand All @@ -19,7 +39,10 @@ def _get_server_info_file_name(use_tmpdir=True):
)
fd, file_name = tempfile.mkstemp(suffix=".txt", prefix="serverinfo-", dir=str(dir_))
os.close(fd)
return file_name
if server_info_dir:
return Path(file_name).name, file_name
else:
return file_name, file_name


def _get_server_info(
Expand Down
7 changes: 5 additions & 2 deletions src/ansys/fluent/core/launcher/slurm_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,11 +416,14 @@ def __init__(
)

def _prepare(self):
self._server_info_file_name = _get_server_info_file_name(use_tmpdir=False)
server_info_file_name_for_server, server_info_file_name_for_client = (
_get_server_info_file_name(use_tmpdir=False)
)
self._server_info_file_name = server_info_file_name_for_client
self._argvals.update(self._argvals["scheduler_options"])
launch_cmd = _generate_launch_string(
self._argvals,
self._server_info_file_name,
server_info_file_name_for_server,
)

self._sifile_last_mtime = Path(self._server_info_file_name).stat().st_mtime
Expand Down
14 changes: 9 additions & 5 deletions src/ansys/fluent/core/launcher/standalone_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,9 @@ def __init__(
exited, or the ``exit()`` method is called on the session instance,
or if the session instance becomes unreferenced. The default is ``True``.
dry_run : bool, optional
Defaults to False. If True, will not launch Fluent, and will instead print configuration information
that would be used as if Fluent was being launched.
Defaults to False. If True, will not launch Fluent, and will print configuration information
that would be used as if Fluent was being launched. If True, the ``call()`` method will return
a tuple containing Fluent launch string and the server info file name.
start_transcript : bool, optional
Whether to start streaming the Fluent transcript in the client. The
default is ``True``. You can stop and start the streaming of the
Expand Down Expand Up @@ -200,10 +201,13 @@ def __init__(
if os.getenv("PYFLUENT_FLUENT_DEBUG") == "1":
self.argvals["fluent_debug"] = True

self._server_info_file_name = _get_server_info_file_name()
server_info_file_name_for_server, server_info_file_name_for_client = (
_get_server_info_file_name()
)
self._server_info_file_name = server_info_file_name_for_client
self._launch_string = _generate_launch_string(
self.argvals,
self._server_info_file_name,
server_info_file_name_for_server,
)

self._sifile_last_mtime = Path(self._server_info_file_name).stat().st_mtime
Expand Down Expand Up @@ -232,7 +236,7 @@ def __init__(
def __call__(self):
if self.argvals["dry_run"]:
print(f"Fluent launch string: {self._launch_string}")
return
return self._launch_string, self._server_info_file_name
try:
logger.debug(f"Launching Fluent with command: {self._launch_cmd}")

Expand Down
27 changes: 27 additions & 0 deletions tests/test_launcher.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import os
from pathlib import Path
import platform
import tempfile
from tempfile import TemporaryDirectory

import pytest
Expand Down Expand Up @@ -498,3 +499,29 @@ def test_fluent_automatic_transcript(monkeypatch):
with TemporaryDirectory(dir=pyfluent.EXAMPLES_PATH) as tmp_dir:
with pyfluent.launch_fluent(container_dict=dict(working_dir=tmp_dir)):
assert not list(Path(tmp_dir).glob("*.trn"))


def test_standalone_launcher_dry_run():
fluent_path = r"\x\y\z\fluent.exe"
fluent_launch_string, server_info_file_name = pyfluent.launch_fluent(
fluent_path=fluent_path, dry_run=True
)
assert str(Path(server_info_file_name).parent) == tempfile.gettempdir()
assert (
fluent_launch_string
== f"{fluent_path} 3ddp -hidden -sifile={server_info_file_name} -nm"
)


def test_standalone_launcher_dry_run_with_server_info_dir(monkeypatch):
with tempfile.TemporaryDirectory() as tmp_dir:
monkeypatch.setenv("SERVER_INFO_DIR", tmp_dir)
fluent_path = r"\x\y\z\fluent.exe"
fluent_launch_string, server_info_file_name = pyfluent.launch_fluent(
fluent_path=fluent_path, dry_run=True
)
assert str(Path(server_info_file_name).parent) == tmp_dir
assert (
fluent_launch_string
== f"{fluent_path} 3ddp -hidden -sifile={Path(server_info_file_name).name} -nm"
)
Loading