Skip to content

Commit

Permalink
Start Fluent container within launch_fluent while building gallery in…
Browse files Browse the repository at this point in the history
… GitHub CI
  • Loading branch information
mkundu1 committed Apr 26, 2022
1 parent bfdb169 commit 5e922bb
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 106 deletions.
12 changes: 0 additions & 12 deletions .ci/stop_fluent.py

This file was deleted.

1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ jobs:
echo "fluentdocs.pyansys.com" >> doc/_build/html/CNAME
env:
ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }}
PYFLUENT_FLUENT_PORT: 63084
PYFLUENT_START_INSTANCE: 0

- name: Upload HTML Documentation
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/nightly-doc-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ jobs:
echo "dev.fluentdocs.pyansys.com" >> doc/_build/html/CNAME
env:
ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }}
PYFLUENT_FLUENT_PORT: 63084
PYFLUENT_START_INSTANCE: 0

- name: Deploy
Expand Down
42 changes: 4 additions & 38 deletions doc/source/conf.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
"""Sphinx documentation configuration file."""
from datetime import datetime
import os
import subprocess
import sys

from pyansys_sphinx_theme import pyansys_logo_black
from sphinx_gallery.sorting import FileNameSortKey

import ansys.fluent.core as pyfluent
from ansys.fluent.core import __version__

# necessary when building the sphinx gallery
pyfluent.BUILDING_GALLERY = True

# -- Project information -----------------------------------------------------

project = "ansys.fluent.core"
Expand Down Expand Up @@ -97,39 +98,6 @@

templates_path = ["_templates"]

_THIS_DIR = os.path.dirname(__file__)
_START_FLUENT_FILE = os.path.normpath(
os.path.join(_THIS_DIR, "..", "..", ".ci", "start_fluent.py")
)
_STOP_FLUENT_FILE = os.path.normpath(
os.path.join(_THIS_DIR, "..", "..", ".ci", "stop_fluent.py")
)


def _start_or_stop_fluent_container(gallery_conf, fname, when):
start_instance = bool(int(os.getenv("PYFLUENT_START_INSTANCE", "1")))
if not start_instance:
if when == "before":
if fname in [
"mixing_elbow_settings_api.py",
"mixing_elbow_tui_api.py",
]:
args = ["3ddp", "-t4", "-meshing"]
elif fname in [
"exhaust_system_settings_api.py",
"exhaust_system_tui_api.py",
]:
args = ["3ddp", "-t2", "-meshing"]
elif fname in [
"parametric_static_mixer_1.py",
"parametric_static_mixer_2.py",
"parametric_static_mixer_3.py",
]:
args = ["3ddp", "-t4"]
subprocess.run([sys.executable, _START_FLUENT_FILE] + args)
elif when == "after":
subprocess.run([sys.executable, _STOP_FLUENT_FILE])


# -- Sphinx Gallery Options ---------------------------------------------------
sphinx_gallery_conf = {
Expand All @@ -152,8 +120,6 @@ def _start_or_stop_fluent_container(gallery_conf, fname, when):
"image_scrapers": ("pyvista", "matplotlib"),
"ignore_pattern": "flycheck*",
"thumbnail_size": (350, 350),
"reset_modules_order": "both",
"reset_modules": (_start_or_stop_fluent_container),
}


Expand Down
2 changes: 2 additions & 0 deletions src/ansys/fluent/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,5 @@ def disable_logging_to_file() -> None:

except:
pass

BUILDING_GALLERY = False
Original file line number Diff line number Diff line change
@@ -1,35 +1,57 @@
import os
import socket
import subprocess
import sys
import tempfile
import time
from typing import List

from ansys.fluent.core import EXAMPLES_PATH

def _get_free_port() -> int:
sock = socket.socket()
sock.bind(("", 0))
return sock.getsockname()[1]

def start_fluent_container(args: List[str]) -> None:

def start_fluent_container(
mounted_from: str, mounted_to: str, args: List[str]
) -> int:
"""Start a Fluent container.
Parameters
----------
mounted_from : str
Path to mount from. ``mounted_from`` will be mounted as ``mount_to``
within the container.
mounted_to : str
Path to mount to. ``mounted_from`` will be mounted as ``mount_to``
within the container.
args : List[str]
List of Fluent launch arguments
Returns
-------
int
gPRC server port exposed from container
"""
fd, sifile = tempfile.mkstemp(
suffix=".txt", prefix="serverinfo-", dir=EXAMPLES_PATH
suffix=".txt", prefix="serverinfo-", dir=mounted_from
)
os.close(fd)
timeout = 100
license_server = os.environ["ANSYSLMD_LICENSE_FILE"]
port = os.environ["PYFLUENT_FLUENT_PORT"]
port = _get_free_port()

try:
subprocess.run(
[
"docker",
"run",
"--name",
"fluent_server",
"-d",
"--rm",
"-p",
f"{port}:{port}",
"-v",
f"{EXAMPLES_PATH}:{EXAMPLES_PATH}",
f"{mounted_from}:{mounted_to}",
"-e",
f"ANSYSLMD_LICENSE_FILE={license_server}",
"-e",
Expand All @@ -52,12 +74,9 @@ def start_fluent_container(args: List[str]) -> None:
break
time.sleep(1)
timeout -= 1
return port
except OSError:
pass
finally:
if os.path.exists(sifile):
os.remove(sifile)


if __name__ == "__main__":
start_fluent_container(sys.argv[1:])
109 changes: 67 additions & 42 deletions src/ansys/fluent/core/launcher/launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import time
from typing import Any, Dict

from ansys.fluent.core.launcher.fluent_container import start_fluent_container
from ansys.fluent.core.session import Session
from ansys.fluent.core.utils.logging import LOG

Expand Down Expand Up @@ -67,6 +68,56 @@ def _get_subprocess_kwargs_for_fluent(env: Dict[str, Any]) -> Dict[str, Any]:
return kwargs


def _build_fluent_launch_args_string(**kwargs) -> str:
"""Build Fluent's launch arguments string from keyword arguments.
Returns
-------
str
Fluent's launch arguments string
"""
all_options = None
with open(_OPTIONS_FILE, encoding="utf-8") as fp:
all_options = json.load(fp)
launch_args_string = ""
for k, v in all_options.items():
argval = kwargs.get(k)
default = v.get("default")
if argval is None and v.get("required") is True:
argval = default
if argval is not None:
allowed_values = v.get("allowed_values")
if allowed_values and argval not in allowed_values:
if default is not None:
old_argval = argval
argval = default
LOG.warning(
"Default value %s is chosen for %s as the passed "
"value %s is outside allowed values %s.",
argval,
k,
old_argval,
allowed_values,
)
else:
LOG.warning(
"%s = %s is discarded as it is outside "
"allowed values %s.",
k,
argval,
allowed_values,
)
continue
fluent_map = v.get("fluent_map")
if fluent_map:
if isinstance(argval, str):
json_key = argval
else:
json_key = json.dumps(argval)
argval = fluent_map[json_key]
launch_args_string += v["fluent_format"].replace("{}", str(argval))
return launch_args_string


# pylint: disable=unused-argument
def launch_fluent(
version: str = None,
Expand Down Expand Up @@ -148,45 +199,7 @@ def launch_fluent(
if start_instance:
exe_path = _get_fluent_exe_path()
launch_string = exe_path
all_options = None
with open(_OPTIONS_FILE, encoding="utf-8") as fp:
all_options = json.load(fp)
for k, v in all_options.items():
argval = argvals.get(k)
default = v.get("default")
if argval is None and v.get("required") is True:
argval = default
if argval is not None:
allowed_values = v.get("allowed_values")
if allowed_values and argval not in allowed_values:
if default is not None:
old_argval = argval
argval = default
LOG.warning(
"Default value %s is chosen for %s as the passed "
"value %s is outside allowed values %s.",
argval,
k,
old_argval,
allowed_values,
)
else:
LOG.warning(
"%s = %s is discarded as it is outside "
"allowed values %s.",
k,
argval,
allowed_values,
)
continue
fluent_map = v.get("fluent_map")
if fluent_map:
if isinstance(argval, str):
json_key = argval
else:
json_key = json.dumps(argval)
argval = fluent_map[json_key]
launch_string += v["fluent_format"].replace("{}", str(argval))
launch_string += _build_fluent_launch_args_string(**argvals)
server_info_filepath = _get_server_info_filepath()
try:
launch_string += f" {additional_arguments}"
Expand Down Expand Up @@ -225,6 +238,18 @@ def launch_fluent(
if server_info_file.exists():
server_info_file.unlink()
else:
ip = argvals.get("ip", None)
port = argvals.get("port", None)
return Session(ip=ip, port=port, cleanup_on_exit=cleanup_on_exit)
import ansys.fluent.core as pyfluent

if pyfluent.BUILDING_GALLERY:
args = _build_fluent_launch_args_string(**argvals).split()
# Assumes the container OS will be able to create the
# EXAMPLES_PATH of host OS. With the Fluent docker
# container, the following currently works only in linux.
port = start_fluent_container(
pyfluent.EXAMPLES_PATH, pyfluent.EXAMPLES_PATH, args
)
return Session(port=port, cleanup_on_exit=cleanup_on_exit)
else:
ip = argvals.get("ip", None)
port = argvals.get("port", None)
return Session(ip=ip, port=port, cleanup_on_exit=cleanup_on_exit)

0 comments on commit 5e922bb

Please sign in to comment.