-
Notifications
You must be signed in to change notification settings - Fork 43
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: Retrieve mesh data in solution mode #3618
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,9 @@ | ||
"""Wrappers over FieldData gRPC service of Fluent.""" | ||
|
||
from dataclasses import dataclass | ||
from enum import Enum | ||
from functools import reduce | ||
import io | ||
from typing import Callable, Dict, List, Tuple | ||
|
||
import grpc | ||
|
@@ -82,6 +84,36 @@ def get_fields(self, request): | |
) | ||
return chunk_iterator | ||
|
||
def get_solver_mesh_nodes( | ||
self, request: FieldDataProtoModule.GetSolverMeshNodesRequest | ||
): | ||
"""GetSolverMeshNodesDouble RPC of FieldData service.""" | ||
chuncked_responses = self._stub.GetSolverMeshNodesDouble( | ||
request, metadata=self._metadata | ||
) | ||
buffer = io.BytesIO() | ||
for chuncked_response in chuncked_responses: | ||
buffer.write(chuncked_response.chunk) | ||
serialized_response = buffer.getvalue() | ||
response = FieldDataProtoModule.GetSolverMeshNodesDoubleResponse() | ||
response.ParseFromString(serialized_response) | ||
return response | ||
|
||
def get_solver_mesh_elements( | ||
self, request: FieldDataProtoModule.GetSolverMeshElementsRequest | ||
): | ||
"""GetSolverMeshElements RPC of FieldData service.""" | ||
chuncked_responses = self._stub.GetSolverMeshElements( | ||
request, metadata=self._metadata | ||
) | ||
buffer = io.BytesIO() | ||
for chuncked_response in chuncked_responses: | ||
buffer.write(chuncked_response.chunk) | ||
serialized_response = buffer.getvalue() | ||
response = FieldDataProtoModule.GetSolverMeshElementsResponse() | ||
response.ParseFromString(serialized_response) | ||
return response | ||
|
||
|
||
class FieldInfo: | ||
"""Provides access to Fluent field information. | ||
|
@@ -922,6 +954,88 @@ def _extract_field(field_datatype, field_size, chunk_iterator): | |
return fields_data | ||
|
||
|
||
@dataclass | ||
class Node: | ||
"""Node class for mesh. | ||
|
||
Attributes: | ||
----------- | ||
x : float | ||
x-coordinate of the node. | ||
y : float | ||
y-coordinate of the node. | ||
z : float | ||
z-coordinate of the node. | ||
""" | ||
|
||
_id: int | ||
x: float | ||
y: float | ||
z: float | ||
|
||
|
||
class CellElementType(Enum): | ||
"""Element types for a cell element.""" | ||
|
||
# 3 nodes, 3 faces | ||
TRIANGLE = 1 | ||
# 4 nodes, 4 faces | ||
TETRAHEDRON = 2 | ||
# 4 nodes, 4 faces | ||
QUADRILATERAL = 3 | ||
# 8 nodes, 6 faces | ||
HEXAHEDRON = 4 | ||
# 5 nodes, 5 faces | ||
PYRAMID = 5 | ||
# 6 nodes, 5 faces | ||
WEDGE = 6 | ||
# Arbitrary number of nodes and faces | ||
POLYHEDRON = 7 | ||
# 2 nodes, 1 face (only in 2D) | ||
GHOST = 8 | ||
# 10 nodes, 4 faces | ||
QUADRATIC_TETRAHEDRON = 9 | ||
# 20 nodes, 6 faces | ||
QUADRATIC_HEXAHEDRON = 10 | ||
# 13 nodes, 5 faces | ||
QUADRATIC_PYRAMID = 11 | ||
# 15 nodes, 5 faces | ||
QUADRATIC_WEDGE = 12 | ||
|
||
|
||
@dataclass | ||
class Element: | ||
"""Element class for mesh. | ||
|
||
Attributes: | ||
----------- | ||
element_type : CellElementType | ||
Element type of the element. | ||
node_indices : list[int] | ||
0-based node indices of the element. | ||
""" | ||
|
||
_id: int | ||
element_type: CellElementType | ||
node_indices: list[int] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Connectivity for polyhedral cells is not yet properly supported. This class will be bit more complex when we support that in future. |
||
|
||
|
||
@dataclass | ||
class Mesh: | ||
"""Mesh class for Fluent field data. | ||
|
||
Attributes: | ||
----------- | ||
nodes : list[Node] | ||
List of nodes in the mesh. | ||
elements : list[Element] | ||
List of elements in the mesh. | ||
""" | ||
|
||
nodes: list[Node] | ||
elements: list[Element] | ||
|
||
|
||
class FieldData: | ||
"""Provides access to Fluent field data on surfaces.""" | ||
|
||
|
@@ -1285,3 +1399,39 @@ def get_pathlines_field_data( | |
field_name: pathlines_data[surface_ids[count]][field_name], | ||
} | ||
return path_lines_dict | ||
|
||
def get_mesh(self, zone_id: int) -> Mesh: | ||
"""Get mesh for a zone. | ||
|
||
Parameters | ||
---------- | ||
zone_id : int | ||
Zone ID. | ||
|
||
Returns | ||
------- | ||
Mesh | ||
Mesh object containing nodes and elements. | ||
""" | ||
request = FieldDataProtoModule.GetSolverMeshNodesRequest( | ||
domain_id=1, thread_id=zone_id | ||
) | ||
response = self._service.get_solver_mesh_nodes(request) | ||
nodes = response.nodes | ||
nodes = [Node(_id=node.id, x=node.x, y=node.y, z=node.z) for node in nodes] | ||
nodes = sorted(nodes, key=lambda x: x._id) | ||
request = FieldDataProtoModule.GetSolverMeshElementsRequest( | ||
domain_id=1, thread_id=zone_id | ||
) | ||
response = self._service.get_solver_mesh_elements(request) | ||
elements = response.elements | ||
elements = [ | ||
Element( | ||
_id=element.id, | ||
element_type=CellElementType(element.element_type), | ||
node_indices=[(id - 1) for id in element.node_ids], | ||
) | ||
for element in elements | ||
] | ||
elements = sorted(elements, key=lambda x: x._id) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: It would be more performant to do the 0-based indexing and sorting in the server-side. Maybe we can eliminate ids at the protobuf layer also. |
||
return Mesh(nodes=nodes, elements=elements) |
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.
We shall have FaceElementType when we support that in future.