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

docs: Update field_data docs. #3510

Merged
merged 2 commits into from
Nov 25, 2024
Merged
Changes from 1 commit
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
177 changes: 87 additions & 90 deletions doc/source/user_guide/fields/field_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,25 @@
Field data
==========

You can use field data objects to access Fluent surface, scalar, vector, and
pathlines data.
You can use field data objects to access Fluent surface, scalar, vector, and pathlines data.

Accessing field data objects
----------------------------

In order to access field data, launch the fluent solver, and make field data
In order to access field data, launch the Fluent solver, and make field data
prmukherj marked this conversation as resolved.
Show resolved Hide resolved
available (for example, either by reading a case file and then initializing as in the following code, or
by reading case and data files).

.. code-block:: python

>>> import ansys.fluent.core as pyfluent
>>> from ansys.fluent.core import examples
>>> import_file_name = examples.download_file("mixing_elbow.msh.h5", "pyfluent/mixing_elbow")
>>> from ansys.fluent.core.examples import download_file
>>> solver = pyfluent.launch_fluent(mode=pyfluent.FluentMode.SOLVER)
>>> solver.settings.file.read(file_type="case", file_name=import_file_name)
>>> solver.settings.solution.initialization.hybrid_initialize()

The field data object is an attribute of the :obj:`~ansys.fluent.core.session_solver.Solver` object:

.. code-block:: python

>>> field_data = solver.fields.field_data
>>> case_path = download_file(file_name="exhaust_system.cas.h5", directory="pyfluent/exhaust_system")
>>> data_path = download_file(file_name="exhaust_system.dat.h5", directory="pyfluent/exhaust_system")
>>> solver.settings.file.read_case_data(file_name=case_path)

>>> field_data = solver.fields.field_data # This creates an instance of the FieldData class.

Simple requests
---------------
Expand All @@ -38,8 +32,8 @@ Here are the methods for requesting each type of field:

- ``get_surface_data`` for surface data.
- ``get_scalar_field_data`` for scalar field data.
- ``get_vector_field_data`` for vector field data
- ``get_pathlines_field_data`` for vector field data
- ``get_vector_field_data`` for vector field data.
- ``get_pathlines_field_data`` for pathlines field data.

Get surface data
~~~~~~~~~~~~~~~~
Expand All @@ -50,89 +44,109 @@ the ``get_surface_data`` method and specifying ``Vertices`` for ``data_types``.

>>> from ansys.fluent.core.services.field_data import SurfaceDataType

>>> vertices_data = field_data.get_surface_data(surfaces=["cold-inlet"], data_types=[SurfaceDataType.Vertices])
>>> vertices_data["cold-inlet"][SurfaceDataType.Vertices].shape
(241, 3)
>>> vertices_data["cold-inlet"][SurfaceDataType.Vertices][5]
array([-0.2 , -0.10167995, 0.00362008], dtype=float32)
>>> vertices_data = field_data.get_surface_data(
>>> surfaces=["inlet"], data_types=[SurfaceDataType.Vertices]
>>> )
# The method retrieves surface vertex coordinates as a NumPy array.
# Shape: (389, 3) - This means 389 vertices, each defined by 3 coordinates (x, y, z).
>>> vertices_data["inlet"][SurfaceDataType.Vertices].shape
(389, 3)
>>> vertices_data["inlet"][SurfaceDataType.Vertices][5]
# Example: The 6th vertex (zero-based indexing) has coordinates [-0.3469, 0.0, -0.0386].
array([-0.34689394, 0. , -0.03863097], dtype=float32)

You can call the same method to get the corresponding surface face normals and centroids.
For ``data_types``, specifying ``FacesNormal`` and ``FacesCentroid`` respectively.
You can call the same method to get the corresponding surface face normals and centroids
by specifying ``FacesNormal`` and ``FacesCentroid`` for ``data_types`` respectively.

.. code-block:: python

>>> faces_normal_and_centroid_data = field_data.get_surface_data(
>>> data_types=[SurfaceDataType.FacesNormal, SurfaceDataType.FacesCentroid], surfaces=["cold-inlet"]
>>> data_types=[SurfaceDataType.FacesNormal, SurfaceDataType.FacesCentroid],
>>> surfaces=["inlet"]
>>> )

>>> faces_normal_and_centroid_data["cold-inlet"][SurfaceDataType.FacesNormal].shape
(152, 3)
>>> faces_normal_and_centroid_data["cold-inlet"][SurfaceDataType.FacesCentroid][15]
array([-0.2 , -0.11418786, 0.03345207], dtype=float32)
# FacesNormal shape: (262, 3) - 262 face normals, each with 3 components (x, y, z).
# FacesCentroid shape: (262, 3) - Centroids for each of the 262 faces, given as (x, y, z).
>>> faces_normal_and_centroid_data["inlet"][SurfaceDataType.FacesNormal].shape
(262, 3)
>>> faces_normal_and_centroid_data["inlet"][SurfaceDataType.FacesCentroid][15]
# Example: The centroid of the 16th face has coordinates [-0.3463, 0.0, -0.0328].
array([-0.34634298, 0. , -0.03276413], dtype=float32)

You can request face connectivity data for given ``surfaces`` by calling
the ``get_surface_data`` method and specifying ``FacesConnectivity`` for ``data_types``.

.. code-block:: python

>>> faces_connectivity_data = field_data.get_surface_data(
>>> data_types=[SurfaceDataType.FacesConnectivity], surfaces=["cold-inlet"]
>>> data_types=[SurfaceDataType.FacesConnectivity], surfaces=["inlet"]
>>> )
>>> faces_connectivity_data["cold-inlet"][SurfaceDataType.FacesConnectivity][5]
array([12, 13, 17, 16])

# FacesConnectivity provides indices of vertices for each face. For example:
# Face 6 is connected to vertices 4, 5, 12, and 11.
>>> faces_connectivity_data["inlet"][SurfaceDataType.FacesConnectivity][5]
array([ 4, 5, 12, 11])

Get scalar field data
~~~~~~~~~~~~~~~~~~~~~
You can call the ``get_scalar_field_data`` method to get scalar field data, such as absolute pressure:

.. code-block:: python

>>> abs_press_data = field_data.get_scalar_field_data(field_name="absolute-pressure", surfaces=["cold-inlet"])
>>> abs_press_data["cold-inlet"].shape
(241,)
>>> abs_press_data["cold-inlet"][120]
101325.0
>>> abs_press_data = field_data.get_scalar_field_data(
>>> field_name="absolute-pressure", surfaces=["inlet"]
>>> )
# Shape: (389,) - A single scalar value (e.g., pressure) for each of the 389 vertices.
>>> abs_press_data["inlet"].shape
(389,)
>>> abs_press_data["inlet"][120]
# Example: The absolute pressure at the 121st vertex is 102031.4 Pascals.
102031.4

Get vector field data
~~~~~~~~~~~~~~~~~~~~~
You can call the ``get_vector_field_data`` method to get vector field data.

.. code-block:: python

>>> velocity_vector_data = field_data.get_vector_field_data(field_name="velocity", surfaces=["cold-inlet"])
>>> velocity_vector_data["cold-inlet"].shape
(152, 3)
>>> velocity_vector_data = field_data.get_vector_field_data(field_name="velocity", surfaces=["inlet", "inlet1"])
# Shape: (262, 3) - Velocity vectors for 262 faces, each with components (vx, vy, vz) for 'inlet'.
>>> velocity_vector_data["inlet"].shape
(262, 3)
# Shape: (265, 3) - Velocity vectors for 265 faces, each with components (vx, vy, vz) for 'inlet1'.
>>> velocity_vector_data["inlet1"].shape
(265, 3)

Get pathlines field data
~~~~~~~~~~~~~~~~~~~~~~~~
You can call the ``get_pathlines_field_data`` method to get pathlines field data.

.. code-block:: python

>>> path_lines_data = field_data.get_pathlines_field_data(field_name="velocity", surfaces=["cold-inlet"])
>>> path_lines_data["cold-inlet"]["vertices"].shape
(76152, 3)
>>> len(path_lines_data["cold-inlet"]["lines"])
76000
>>> path_lines_data["cold-inlet"]["velocity"].shape
(76152, )
>>> path_lines_data["cold-inlet"]["lines"][100]
>>> path_lines_data = field_data.get_pathlines_field_data(
>>> field_name="velocity", surfaces=["inlet"]
>>> )
# Vertices shape: (29565, 3) - 29565 pathline points, each with coordinates (x, y, z).
# Lines: A list where each entry contains indices of vertices forming a pathline.
# Velocity shape: (29565,) - Scalar velocity values at each pathline point.
>>> path_lines_data["inlet"]["vertices"].shape
(29565, 3)
>>> len(path_lines_data["inlet"]["lines"])
29303
>>> path_lines_data["inlet"]["velocity"].shape
(29565,)
>>> path_lines_data["inlet"]["lines"][100]
# Example: Pathline 101 connects vertices 100 and 101.
array([100, 101])

Dictionary containing a map of surface IDs to the path-line data is returned.
For example, pathlines connectivity, vertices, and field.


Making multiple requests in a single transaction
------------------------------------------------
You can get data for multiple fields in a single transaction.

First create transaction object for field data.
First, create a transaction object for field data.

.. code-block:: python

>>> transaction = solver.fields.field_data.new_transaction()
# This creates a new transaction object for batching multiple requests.

Then combine requests for multiple fields using ``add_<items>_request`` methods in a single transaction:

Expand All @@ -141,55 +155,39 @@ Then combine requests for multiple fields using ``add_<items>_request`` methods
- ``add_vector_fields_request`` adds a vector fields request.
- ``add_pathlines_fields_request`` adds a pathlines fields request.

Following code demonstrate adding multiple requests to a single transaction.

.. code-block::
.. code-block:: python

>>> transaction.add_surfaces_request(
>>> surfaces=[1], data_types = [SurfaceDataType.Vertices, SurfaceDataType.FacesCentroid],
>>> )
>>> transaction.add_surfaces_request(
>>> surfaces=[2], data_types = [SurfaceDataType.Vertices, SurfaceDataType.FacesConnectivity],
>>> surfaces=[1], data_types=[SurfaceDataType.Vertices, SurfaceDataType.FacesCentroid]
>>> )
# Adds a request for surface data such as vertices and centroids.
>>> transaction.add_scalar_fields_request(
>>> surfaces=[1,2], field_name="pressure", node_value=True, boundary_value=True
>>> surfaces=[1, 2], field_name="pressure", node_value=True, boundary_value=True
>>> )
>>> transaction.add_vector_fields_request(surfaces=[1,2], field_name="velocity")
>>> transaction.add_pathlines_fields_request(surfaces=[1,2], field_name="temperature")

# Adds a request for scalar field data like pressure.
>>> transaction.add_vector_fields_request(
>>> surfaces=[1, 2], field_name="velocity"
>>> )
# Adds a request for vector field data like velocity.

You can call the ``get_fields`` method to get the data for all these requests. This call also
clears all requests, so that subsequent calls to the ``get_fields`` method yield nothing until
more requests are added.
You can call the ``get_fields`` method to execute the transaction and retrieve the data:

.. code-block::
.. code-block:: python

>>> payload_data = transaction.get_fields()
# Executes all requests and returns the combined field data.

``payload_data`` is a dictionary containing the requested fields as a numpy array in the following order:

``tag -> surface_id [int] -> field_name [str] -> field_data[np.array]``

.. note::
``get_fields`` call also clears all requests, so that subsequent calls to this method
yield nothing until more requests are added.


Tag
---

Fluent versions earlier than 2023 R1
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A tag is int, generated by applying ``bitwise or`` on all tags for a request. Here is a list
of supported tags and their values:

* OVERSET_MESH: 1,
* ELEMENT_LOCATION: 2,
* NODE_LOCATION: 4,
* BOUNDARY_VALUES: 8,

For example, if you request the scalar field data for element location[2], in the
dictionary, ``tag`` is ``2``. Similarly, if you request the boundary values[8] for
node location[4], ``tag`` is ``(4|8)`` or 12.

Fluent versions 2023 R1 and later
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A tag is tuple of input, value pairs for which field data is generated.

For example, if you request the scalar field data for element location, in the
Expand All @@ -216,7 +214,6 @@ depending on the request arguments:
- ``centroid``, which contains face centroids
- ``face-normal``, which contains face normals


Scalar field request
~~~~~~~~~~~~~~~~~~~~
The response to a scalar field request contains a single field with the same
Expand Down Expand Up @@ -256,17 +253,17 @@ Some sample use cases are demonstrated below:

>>> field_data.get_scalar_field_data.field_name.allowed_values()
['abs-angular-coordinate', 'absolute-pressure', 'angular-coordinate',
'anisotropic-adaption-cells', 'axial-coordinate', 'axial-velocity',
'anisotropic-adaption-cells', 'aspect-ratio', 'axial-coordinate', 'axial-velocity',
'boundary-cell-dist', 'boundary-layer-cells', 'boundary-normal-dist', ...]

>>> transaction = field_data.new_transaction()
>>> transaction.add_scalar_fields_request.field_name.allowed_values()
['abs-angular-coordinate', 'absolute-pressure', 'angular-coordinate',
'anisotropic-adaption-cells', 'axial-coordinate', 'axial-velocity',
'anisotropic-adaption-cells', 'aspect-ratio', 'axial-coordinate', 'axial-velocity',
'boundary-cell-dist', 'boundary-layer-cells', 'boundary-normal-dist', ...]

>>> field_data.get_scalar_field_data.surface_name.allowed_values()
['cold-inlet', 'hot-inlet', 'outlet', 'symmetry-xyplane', 'wall-elbow', 'wall-inlet']
['in1', 'in2', 'in3', 'inlet', 'inlet1', 'inlet2', 'out1', 'outlet', 'solid_up:1', 'solid_up:1:830', 'solid_up:1:830-shadow']

>>> field_data.get_surface_data.surface_ids.allowed_values()
[0, 1, 2, 3, 4, 5]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]