-
Notifications
You must be signed in to change notification settings - Fork 40
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
[S549767] Start Fluent from PyFluent #7
Conversation
processor_count: | ||
type: int | ||
fluent_format: " -t{}" | ||
journal_filename: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that Fluent supports multiple specifications of -i <joufile>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@HKrishnan-ansys will add different type for journal_filename to handle it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless you pass the -cloud option... :-) Learned that this week.
ansys/fluent/session.py
Outdated
if self.__channel: | ||
self.__channel.close() | ||
Path(self.server_info_filepath).unlink(missing_ok=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file can be deleted as soon as the connection is done, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, thanks
ansys/fluent/launcher/launcher.py
Outdated
argval = fluent_values[i] | ||
launch_string += v['fluent_format'].replace('{}', str(argval)) | ||
server_info_filepath = get_server_info_filepath() | ||
launch_string += f' -sifile="{server_info_filepath}"' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mkundu1 Sorry to be finicky here but I am wondering if it is better to remove the file in this place in a try-finally block (you may want to put the unlink call also in a try-except block).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@HKrishnan-ansys No problem, yeah that's better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
ansys/fluent/launcher/launcher.py
Outdated
FLUENT_MAJOR_VERSION = '22' | ||
FLUENT_MINOR_VERSION = '2' | ||
LAUNCH_FLUENT_TIMEOUT = 100 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These all will have to be user configurable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, and is there a reason to split them apart into two variables? Why not just FLUENT_VERSION='22.2'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to FLUENT_VERSION='22.2'
ansys/fluent/launcher/launcher.py
Outdated
version = None, | ||
precision = None, | ||
processor_count = None, | ||
journal_filename = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: there should be no whitespace between =
for keyword args.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, is that part of the formatting guidelines already?
ansys/fluent/launcher/launcher.py
Outdated
|
||
Returns | ||
------- | ||
An instance of ansys.fluent.session.Session. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should follow numpy doc Returns style:
An instance of ansys.fluent.session.Session. | |
ansys.fluent.session.Session | |
Fluent session. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed docstring to follow numpydoc style
ansys/fluent/launcher/launcher.py
Outdated
"""Start Fluent locally in server mode. | ||
Parameters |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There has to be whitespace between short description and the Parameters section.
"""Start Fluent locally in server mode. | |
Parameters | |
"""Start Fluent locally in server mode. | |
Parameters |
ansys/fluent/launcher/launcher.py
Outdated
Whether to use the '2d' or '3d' version of Fluent. Default is '3d'. | ||
|
||
precision : str, optional | ||
Whether to use the single-precision or double-precision version of Fluent. Default is double-precision. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Be sure to escape literals.
Also, consider that the PEP8 standard for docstring length is 72:
PEP8 has some maximum line length guidelines, starting with “Limit all lines to a maximum of 79 characters” but “for flowing long blocks of text with fewer structural restrictions (docstrings or comments), the line length should be limited to 72 characters.”
I'm ok if we go to 79, but any longer and it won't be rendered correctly in some "old school" editors.
Whether to use the single-precision or double-precision version of Fluent. Default is double-precision. | |
Whether to use the single-precision or double-precision version of Fluent. Default is ``"double-precision"``. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree we should stick to PEP8 here.
ansys/fluent/launcher/launcher.py
Outdated
print(f'Default value {argval} is chosen for {k} as the passed value ' | ||
f'{old_argval} is outside allowed_values {allowed_values}.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't print, either warn or raise. This won't show up in unit testing and users could potentially be passing invalid args.
ansys/fluent/launcher/launcher.py
Outdated
if argval is None and v.get('required', None) == True: | ||
argval = default | ||
if argval is not None: | ||
allowed_values = v.get('allowed_values', None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that None
is redundant for get
. If a key does not exist, None
is returned by default
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that would clean it up.
ansys/fluent/launcher/launcher.py
Outdated
for k, v in all_options.items(): | ||
argval = argvals.get(k, None) | ||
default = v.get('default', None) | ||
if argval is None and v.get('required', None) == True: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sure you know, but: https://stackoverflow.com/questions/27276610/boolean-identity-true-vs-is-true
if argval is None and v.get('required', None) == True: | |
if argval is None and v.get('required') is True: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks
ansys/fluent/launcher/launcher.py
Outdated
launch_string += f' -sifile="{server_info_filepath}"' | ||
if not os.getenv('PYFLUENT_SHOW_SERVER_GUI'): | ||
launch_string += ' -hidden' | ||
print(f'Launching Fluent with cmd: {launch_string}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be using logging here, avoid printing always.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a basic logger class to log to console - will expand that to include log files, etc. in future.
ansys/fluent/launcher/launcher.py
Outdated
while True: | ||
if Path(server_info_filepath).stat().st_mtime > sifile_last_mtime: | ||
time.sleep(1) | ||
print('\nFluent process is successfully launched.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See logging note.
ansys/fluent/session.py
Outdated
def parse_server_info_file(filename: str): | ||
with open(filename, "rb") as f: | ||
lines = f.readlines() | ||
return (lines[0].strip(), lines[1].strip()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary tuple:
return (lines[0].strip(), lines[1].strip()) | |
return lines[0].strip(), lines[1].strip() |
ansys/fluent/session.py
Outdated
self.__channel = grpc.insecure_channel(address) | ||
datamodel_stub = DataModelGrpcModule.DataModelStub(self.__channel) | ||
self.service = DatamodelService(datamodel_stub, password) | ||
self.tui = Session.tui(self.service) | ||
|
||
def stop(self): | ||
def close(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Provide documentation here please.
README.rst
Outdated
@@ -40,5 +36,5 @@ In Python (client-side): | |||
session.tui.display.objects.contour['contour-1'].color_map.size() | |||
session.tui.display.objects.contour['contour-1'].rename('my-contour') | |||
del session.tui.display.objects.contour['my-contour'] | |||
session.stop() | |||
session.close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious, and it's up to you, but should we have close
or exit
. Close implies you're closing the connection, while exit implies you're shutting down the fluent instance. I can't tell (as a user/onlooker) what close
is doing since there's no docstring.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it means close the connection right? i.e. I can connect again later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed this to session.exit
. session.exit
closes the connection and exit Fluent. At present we cannot re-use the session object - will check if we should do it. Perhaps, we shall recommend users to use session within a with context.
print(f'Launching Fluent with cmd: {launch_string}') | ||
sifile_last_mtime = Path(server_info_filepath).stat().st_mtime | ||
kwargs = get_subprocess_kwargs_for_detached_process() | ||
subprocess.Popen(launch_string, **kwargs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider piping stdout/stderr to a listener thread that writes to a logger. That way users can determine why fluent fails to launch. I've tried a similar implementation for MAPDL, but there's an issue with stdout/stderr piping otherwise we would have implemented it; I hope you don't encounter the same issue here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I'll check this.
ansys/fluent/launcher/launcher.py
Outdated
print('\nFluent process is successfully launched.') | ||
break | ||
if counter == 0: | ||
print('\nThe launch process has been timed out.') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Warn or raise.
ansys/fluent/launcher/launcher.py
Outdated
break | ||
time.sleep(1) | ||
counter -= 1 | ||
print(f'Waiting for Fluent to launch...{counter:2} seconds remaining', end='\r') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Log this.
README.rst
Outdated
@@ -40,5 +36,5 @@ In Python (client-side): | |||
session.tui.display.objects.contour['contour-1'].color_map.size() | |||
session.tui.display.objects.contour['contour-1'].rename('my-contour') | |||
del session.tui.display.objects.contour['my-contour'] | |||
session.stop() | |||
session.close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it means close the connection right? i.e. I can connect again later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mainak, please incorporate the suggestions from Alex.
return str(exe_path) | ||
|
||
def get_server_info_filepath(): | ||
server_info_dir = os.getenv('SERVER_INFO_DIR') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What sets up this environment variable? I guess we should also add keyword options to pass the IP/hostname and port to the lauch_fluent function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, we'll need to change launcher.py to pass the host/port info for docker launch. Current it assumes Fluent is launched from a local machine. SERVER_INFO_DIR
is documented feature in Fluent to specify the location of the server-info file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mkundu1 Could we use temp folder instead of Path.cwd() if SERVER_INFO_DIR is not specified?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can use the temp folder, will change it in the next PR.
Thanks @akaszynski and @dnwillia-ansys for your valuable suggestions. I've incorporated most of them. There are a couple remaining, will look into those in subsequent PRs. |
journal_filename : str, optional | ||
Read the specified journal file. | ||
|
||
start_timeout : float, optional |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mkundu1 Is this float or int?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix in next PR
Add a launch_fluent method which will launch Fluent and return a Session instance. Currently launch_fluent supports only few common arguments to launch Fluent locally which are validated and converted to Fluent launch arguments using static information from launch_options.yaml file. Minor change is required in Fluent side to cleanly exit Fluent from PyFluent which has added in PR 290947.
PyFluent should cover some of the launch_mapdl arguments (#5) - will look into these separately. Some of these like start_timeout should be handled in the client side.