ansys / pyfluent Goto Github PK
View Code? Open in Web Editor NEWPythonic interface to Ansys Fluent
Home Page: https://fluent.docs.pyansys.com
License: MIT License
Pythonic interface to Ansys Fluent
Home Page: https://fluent.docs.pyansys.com
License: MIT License
Submit a command like:
solution.run_calculation.iterate(number_of_iterations=100)
and no residuals... :-)
The adjoint/observable menus are not generated in PyFluent as those are inserted in Fluent only when adjoint module is loaded. We need to pull these at runtime from Fluent.
To reproduce:
In the Settings Object page, under "Setting and Modifying State",
Replace:
root.setup.boundary_conditions.velocity['inlet1'].vmag.constant()
With:
root.setup.boundary_conditions.velocity_inlet['inlet1'].vmag.constant()
I think that using operator= to set_state is powerful but there is arguably a drawback that should be discussed.
I take aliases everywhere to simplify the code and everywhere do:
x.y.z.foo()
or equivalently:
z = x.y.z
z.foo()
This is fine for method calls but assignment at the level of z is pure assignment (that is not forwarded to set_state).
This is Pythonic, but I don't like it.
Looking through the code today, and a few of the other pansys modules, I think it would be good if we organized things so it's clear what modules/packages contain external public APIs and what are implementation. For instance, see the image below. Everything with a red line looks public to me, everything with green line is hidden (but we want to make it public soon) and everything with a blue line is implementation.
I'm not sure about the best way to organize it, but I think we should try and do something a bit different here. Would it make sense to follow a convention to separate packages into private and public like you can do in the modules. eg:
ansys/fluent/_impl1 # Implementation package 1
ansys/fluent/_impl2 # Implementation package 2
ansys/fluent/api1 # Public API package 1
ansys/fluent/api1/moduleA.py # Public module A in api1
ansys/fluent/api1/_moduleB.py # Private module B in package api1
ansys/fluent/api2 # Public API package 2
ansys/fluent/api2/moduleA.py # Public module A in api2
and so on. The documentation builds can then be configured to only look at the public packages and public modules within those packages, testing only needs to be created for the public APIs etc..
There are packages such as codegen as well. This module needs some documentation but it's more of a utility thing, maybe we could rename the area to 'utilities' and not package it with the wheel or something.
We need to publish the version of grpcio-tools used to generate the protobuf Python modules. eg: in a requirements file so that I can configure a virutal environment to generate them if I want.
Raw strings are returned from Fluent commands:
'Fast-loading "D:\\ANSYSDev\\NoBackup\\fluent\\v222\\fluent\\fluent22.2\\\\addons\\afd\\lib\\hdfio.bin"\nDone.\nMulticore processors detected. Processor affinity set!\n\nReading from watdnwillia2:"D:/ANSYSDev/NoBackup/afd/AFD/Tests/Flux/Proprietary/ge-hood/hood_221_cfxresiduals.cas.h5" in NODE0 mode ...\n Reading mesh ...\n 2726232 cells, 1 cell zone ...\n 2726232 mixed cells, zone id: 1\n 5782778 faces, 7 face zones ...\n 3047 triangular wall faces, zone id: 2\n 99932 triangular wall faces, zone id: 3\n 2297 mixed pressure-inlet faces, zone id: 4\n 6489 mixed wall faces, zone id: 5\n 28855 triangular wall faces, zone id: 6\n 986 mixed pressure-outlet faces, zone id: 7\n 5641172 mixed interior faces, zone id: 9\n 672773 nodes, 1 node zone ...\nWarning: reading 4 partition grid onto 2 compute node machine.\n Combining every 2 partitions.\n Done.\n\n\nBuilding...\n mesh\n\tdistributing mesh\n\t\tparts..,\n\t\tfaces..,\n\t\tnodes..,\n\t\tcells..,\n bandwidth reduction using Reverse Cuthill-McKee: 1368839/17878 = 76.5656\n materials,\n interface,\n domains,\n\tmixture\n zones,\n\tdefault-interior\n\toutlet\n\touter-wall\n\tinv-wall\n\tdefault\n\tbearing-cone\n\tinlet\n\ttao-335-mod\n parallel,\nDone.\n\nPreparing mesh for display...\nDone.\n'
Would be better if this was expanded to include the new lines in the local session.
While creating xy plots, pathlines and particle tracks the pyfluent script creation becomes too complex. can someone please look into it?
From @seanpearsonuk
It would be nice if each instance could also connect to the healthcheck service:
status = f1.status()
@mkundu1 Can't remember where we got to with this behaviour. This is in connection with this issue: #88 where @sujal-tipnis sent the wrong string to initialize the workflow. We could detect the failure if the client command returned the value as returned in the application but it's coming back as None. Let me have a look.
I suggest we have a module per service which wraps that service's grpc calls, rather than importing the _pb2 files in many modules.
Originally posted by @h-krishnan in #21 (comment)
Hello Team,
Greetings!
While executing following snippet, encounter mentioned issue,
Please find detailed traceback attached.
python_traceback.txt
import ansys.fluent as pyfluent
pyfluent.set_log_level('DEBUG')
session = pyfluent.launch_fluent()
session.check_health()
following are the version details;
ANSYS Fluent 2022 R2
Build Time: Feb 24 2022 12:51:39 EDT Build Id: 132 Revision: 4e4c04dcf9 Branch: develop
Please let me know if I am missing something on installation/process.
Thanks and Regards,
Abhishek
Current example from the Settings API follows. We should aim to make everything clearly and explicitly named, and unabbreviated.
>>> root.setup.boundary_conditions.pressure_outlet['pressure-outlet-7'].get_state().keys()
dict_keys(['frame_of_reference', 'p', 'p_profile_multiplier', 't0', 'direction_spec', 'ke_spec', 'turb_intensity', 'turb_hydraulic_diam', 'p_backflow_spec_gen', 'prevent_reverse_flow', 'radial', 'avg_press_spec', 'targeted_mf_boundary'])
To reproduce:
To reproduce:
Check the dictionary created.
The default surfaces list is not selected as it should be.
To reproduce:
_import ansys.fluent as pyfluent
import os
path = os.getcwd()
s= pyfluent.launch_fluent()
s.check_health()
s.tui.solver.file.show_configuration()
s.tui.solver.file.read_case(case_file_name=path + '/mesh_files/mixing_tank.msh')
root = s.get_settings_root()
s.tui.solver.define.operating_conditions.gravity("yes","0","0","-9.81")
s.tui.solver.define.operating_conditions.operating_density("yes", "1.225")
root.setup.models.multiphase.models = 'eulerian'_
Now when I print status of the viscous model, I do not see the Turbulence Multiphase Model options as seen below:
root.setup.models.viscous.print_state()
model : k-omega-standard
options :
curvature_correction : False
corner_flow_correction : False
production_kato_launder : False
production_limiter : True
k_omega_model : sst
k_omega_options :
kw_low_re_correction : False
The subsequent Fluent GUI has the following options:
When I run the following:
import ansys.fluent as pyfluent
session = pyfluent.launch_fluent()
root = session.get_settings_root()
I get this error:
AttributeError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_10076\1999831875.py in
1 session = pyfluent.launch_fluent()
----> 2 root = session.get_settings_root()AttributeError: 'Session' object has no attribute 'get_settings_root'
Am I doing something wrong?
I set state as {'FileName':'x.scdoc.pmdb','AppendMesh':True} but when I get it subsequently, it comes back as {'file_name': 'x.scdoc.pmdb', 'append_mesh': True}
I don't think we should transform this. If we do transform the names, we should do it consistently, such that file_name and not FileName is a valid input (which would be tricky to enforce). Haven't checked but I guess this shows up quite generally in meshing workflow.
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.
Originally posted by @akaszynski in #7 (comment)
Currently you start up Fluent, then manually start the server, then connect to it by telling the Python interface to read a server info file.
Let's consolidate this with PyMAPDL and add a launch_fluent command with similar/same arguments as APDL. Probably some new Fluent command line argument(s) are needed.
Start a session and quit():
import ansys.fluent.solver as pyfluent
session = pyfluent.launch_fluent()
quit() # This hangs
Issuing a command such as:
solution.run_calculation.iterate(number_of_iterations=100)
can take a while and if you want to interrupt it with control-C that does not work.
or... we start implementing asynchronous objects.
Looks like maybe yaml is required in the virtual environment now:
(venv) D:\ANSYSDev\NoBackup\pyansys\pyfluent>python
Python 3.8.10 (tags/v3.8.10:3d8993a, May 3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import ansys.fluent.solver as pyfluent
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\ANSYSDev\NoBackup\pyansys\pyfluent\ansys\fluent\solver\__init__.py", line 4, in <module>
from ansys.fluent.launcher.launcher import launch_fluent
File "D:\ANSYSDev\NoBackup\pyansys\pyfluent\ansys\fluent\launcher\launcher.py", line 8, in <module>
import yaml
ModuleNotFoundError: No module named 'yaml'
Probably time for a requirements.txt file with these dependencies. Though, it begs the question, why the dependency?
You get this error when running the module to regenerate some of the automatically generated files:
(venv) D:\ANSYSDev\NoBackup\pyansys\pyfluent>python
Python 3.8.10 (tags/v3.8.10:3d8993a, May 3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from codegen.tuigen import TUIGenerator
>>> TUIGenerator().generate()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "D:\ANSYSDev\NoBackup\pyansys\pyfluent\codegen\tuigen.py", line 169, in generate
self.session.exit()
File "D:\ANSYSDev\NoBackup\pyansys\pyfluent\ansys\fluent\session.py", line 124, in exit
self.tui.exit()
AttributeError: 'Tui' object has no attribute 'exit'
>>>
__setattr__
for PyMenuMetaconvert_path_to_grpc_path
should be used within datamodel_tui.PyMenu
To reproduce:
Traceback (most recent call last):
File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.3.1\plugins\python-ce\helpers\pydev_pydev_bundle\pydev_console_utils.py", line 261, in do_get_completions
return completer.complete(act_tok)
File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.3.1\plugins\python-ce\helpers\pydev_pydev_bundle_pydev_completer.py", line 89, in complete
return self.attr_matches(text)
File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.3.1\plugins\python-ce\helpers\pydev_pydev_bundle_pydev_completer.py", line 151, in attr_matches
words = dir2(obj, filter=filter)
File "C:\Program Files\JetBrains\PyCharm Community Edition 2021.3.1\plugins\python-ce\helpers\pydev_pydev_bundle_pydev_imports_tipper.py", line 179, in generate_imports_tip_for_module
if hasattr(obj_to_complete, 'dict'):
File "e:\pyfluent\pyfluent\ansys\fluent\services\datamodel_se.py", line 349, in getattr
return self.__get_child(name)
File "e:\pyfluent\pyfluent\ansys\fluent\services\datamodel_se.py", line 286, in __get_child
se_name = convert_python_name_to_se_name(name)
File "e:\pyfluent\pyfluent\ansys\fluent\services\datamodel_se.py", line 174, in convert_python_name_to_se_name
return "".join([x[0].upper() + x[1:] for x in python_name.split("")])
File "e:\pyfluent\pyfluent\ansys\fluent\services\datamodel_se.py", line 174, in
return "".join([x[0].upper() + x[1:] for x in python_name.split("")])
IndexError: string index out of range
In current approach following commands are valid
c1=session.tui.display.objects.contour['contour-1']
c2=c1["contour-2"]
It does not look good. Instead we should have container object to manage children.
Originally posted by @ajain-ansys in #21 (comment)
Support flake8-annotations IDs from #41
I have concerns about some performance overheads here:
Originally posted by @h-krishnan in #81 (comment)
Hi,
I've been playing around with PyFluent and I faced some issues/questions that may be worth commenting:
What is the different between Solver and SolverTui (same for Meshing)?
How can we access documentation about argument types, input formats, meanings, etc.? I see some functions have this documented but some others not (I guess not yet...), i.e.
Thanks,
To reproduce:
If I have an erroneous command input like:
session.tui.solver.define.models.viscous.kw_geko('blabla')
then it is printed in the transcript and the console:
/define/models/viscous/kw-geko? /define/models/viscous/kw-geko? yes/define/models/viscous/kw-geko? blablaPlease answer y[es] or n[o].
However, if a command is correctly executed, the output in the console is not very helpful:
In[46]: session.tui.solver.define.models.viscous.kw_geko('yes')
Out[46]: <ansys.fluent.services.datamodel_tui.PyMenu.ExecuteCommandResult at 0x1a5360c4ee0>
and the transcript is empty. This will lead to difficulty in realizing what commands were run when reviewing the transcript. The transcript and console should show:
> define/models/viscous/kw-geko yes
Edit: Also recommending an explicit output to the python console to show whether a command was successfully or wrongfully executed. Ref #81 (comment)
import ansys.fluent as pyfluent
session = pyfluent.launch_fluent(meshing_mode=True)
session.workflow.initialize_workflow(WorkflowType="Watertight Geometry")
session.workflow.task_object['Import Geometry'].arguments.help()
and
dir(session.workflow.task_object['Import Geometry'].arguments)
both crash the server
Just walking through the code, there are some documentation issues:
In the readme it says the following:
A Group object is a static container with pre-defined child objects which can be accessed via attribute access. For example, setup.models.energy refers to the energy child of models child of the setup object. The names of the child objects of a group can be accessed with the child_names attribute of a Group object.
However, it appears that I need to use member_names, not child names.
I notice that the two ways to evaluate scheme comands give different return types:
The "low-level" approach using eval() returns a Python object of a matching type to the scheme value:
session._Session__scheme_eval.eval(S("rpgetvar"), [S('string->symbol'), "example-list"]])
[1, 2, 3, 4]
But the more user friendly, "direct" function, string_eval() :
session._Session__scheme_eval.string_eval("(rpgetvar 'example-list)")
returns a string:
'(1 2 3 4)'
Could the second approach return the same as the first?
This would be more useful to users, otherwise they have to deconstruct complex strings into python objects.
Or, provide a third way that takes in a "raw" scheme string like string_eval() and returns a Python value like eval :
session._Session__scheme_eval.eval_scheme("(rpgetvar 'example-list)")
that returns:
[1, 2, 3, 4]
But, having 3 different ways would be confusing.
I assume it is eventually planned to make this more visible in the structure, such as near the top of the session tree.:
session.eval_scheme("(rpgetvar 'example-list)")
Thanks,
Adam
When I try to "import ansys.fluent as pyfluent". I am getting the following error:
Traceback (most recent call last):
File "", line 1, in
File "e:\pyfluent\pyfluent\ansys\fluent_init.py", line 2, in
from ansys.fluent.launcher.launcher import launch_fluent # noqa: F401
File "e:\pyfluent\pyfluent\ansys\fluent\launcher\launcher.py", line 11, in
from ansys.fluent.session import Session
File "e:\pyfluent\pyfluent\ansys\fluent\session.py", line 19, in
from ansys.fluent.services.settings import SettingsService
File "e:\pyfluent\pyfluent\ansys\fluent\services\settings.py", line 4, in
from ansys.api.fluent.v0 import settings_pb2 as SettingsModule
ImportError: cannot import name 'settings_pb2' from 'ansys.api.fluent.v0' (C:\Program Files (x86)\Python38-32\lib\site-packages\ansys\api\fluent\v0_init_.py)_
This is seen with the latest Fluent and the latest pyfluent repo.
The correct command to be used is:
session.tui.solver.adjoint.observable("write", "yes", '''"out/adjoint-obs.monset"''')
but when I write it partially as:
session.tui.solver.adjoint.observable("write", "yes")
the python console floods with this output:
Using Spyder, have to end task forcefully. Easily reproducible.
To reproduce (have to define the observable before printing it), please see the attached file and change line 7 and 30.
simple-case.zip
To reproduce:
Start PyFluent in the meshing mode.
Initialize FTM workflow using the script given below:
s.workflow.initialize_workflow(workflow_type='Fault-Tolerant Meshing')
FTM workflow fails to initialize
@seanpearsonuk @mkundu1 can you please look into this?
To reproduce:
import ansys.fluent as pyfluent
session = pyfluent.launch_fluent(meshing_mode=True)
session.workflow.initialize_workflow(workflow_type='Watertight Geometry')
session.workflow.task_object['Import Geometry'].arguments = dict(file_name='elbow-geometry.scdoc.pmdb')
session.workflow.task_object['Import Geometry'].execute()
Any geometry should be fine while importing.
Use the dir method to list the attributes of the method arguments as shown below:
dir(session.workflow.task_object['Add Local Sizing].arguments)
This causes Fluent to crash.
After closing the Fluent window, following stack trace is seen in the command prompt terminal. Please check the text file for the stack trace.
I am testing on Windows 64, latest PyFluent and Fluent.
Build Time: Mar 1 2022 06:31:59 EDT Build Id: 137 Revision: 3a03865a78 Branch: develop
To reproduce:
######### Error ########
import ansys.fluent as pyfluent
session=pyfluent.launch_fluent(precision="double",processor_count="4")
session.setup_settings_objects()
Traceback (most recent call last):
File "<pyshell#2>", line 1, in
session.setup_settings_objects()
File "c:\users\ypatel\pyfluent\pyfluent\ansys\fluent\session.py", line 107, in setup_settings_objects
r = flobject.get_root(flproxy=proxy)
File "c:\users\ypatel\pyfluent\pyfluent\ansys\fluent\solver\flobject.py", line 606, in get_root
cls = get_cls('', obj_info)
File "c:\users\ypatel\pyfluent\pyfluent\ansys\fluent\solver\flobject.py", line 569, in get_cls
ccls = get_cls(cname, cinfo, cls)
File "c:\users\ypatel\pyfluent\pyfluent\ansys\fluent\solver\flobject.py", line 592, in get_cls
get_cls(cls.name + '-object-type', object_type, cls)
File "c:\users\ypatel\pyfluent\pyfluent\ansys\fluent\solver\flobject.py", line 569, in get_cls
ccls = get_cls(cname, cinfo, cls)
File "c:\users\ypatel\pyfluent\pyfluent\ansys\fluent\solver\flobject.py", line 592, in get_cls
get_cls(cls.name + '-object-type', object_type, cls)
File "c:\users\ypatel\pyfluent\pyfluent\ansys\fluent\solver\flobject.py", line 569, in get_cls
ccls = get_cls(cname, cinfo, cls)
File "c:\users\ypatel\pyfluent\pyfluent\ansys\fluent\solver\flobject.py", line 553, in get_cls
base = _baseTypes[obj_type]
KeyError: 'map'
Currently the readme has this:
import ansys.fluent as pyfluent
#...
session = pyfluent.launch_fluent()
session.check_health()
session.tui.solver.file.read_case(case_file_name='elbow.cas.gz')
# etc
check_health()
just returns a string to indicate the health, where 'SERVING' is the 'normal' response. Other values are 'NOT SERVING', 'UNKNOWN', and 'SERVICE UNKNOWN' (which is only used by the watch method).
We should check health without dependency on string values: the user might wonder if writing assert check_health() == 'SERVING'
is valid or is there a broader range of strings that does not denote errors. Even if the assert is correct now, can it become broken over time? Simple extensions might be:
session.is_health_check_ok()
session.assert_health_check_ok()
These would encapsulate the logic of determining what is OK, what is not OK. One also might want to call
session.is_serving()
What is the health check postcondition for launch_fluent()? I believe it should be defined. If the postcondition is health == 'SERVING' (or some other criterion) what should the behaviour be if that is not met? The point about the question is whether there is any point in having the session object in this scenario or can we emit an exception (after cleaning up the server if possible)? That design would be preferable.
Should we expose the health check watch method on the session?
@dnwillia-work @mkundu1 @h-krishnan @ajain-work @lagacep-ans
>>> import ansys.fluent.postprocessing.pyvista as pv
>>> graphics = pv.Graphics(session)
>>> vector = graphics.Vectors["vector-1"]
>>> vector.bob
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Vector' object has no attribute 'bob'
>>> vector.bob = 42
>>> vector.bob
42
To reproduce:
This is what I had tried:
import ansys.fluent as pyfluent
import os
path = os.getcwd()
s = pyfluent.launch_fluent(meshing_mode=True)
s.workflow.initialize_workflow(workflow_type='Fault-tolerant Meshing')
s.part_management.load_fmd_file(FilePath=r'exhaust_system.fmd', FileUnit=r'mm', JtLOD=r'1', PartPerBody=False, Route=r'Native')
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.