-
Notifications
You must be signed in to change notification settings - Fork 25
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
Add mesh tutorials to the main tutorials branch #1908
base: doc/new-tutorials-section
Are you sure you want to change the base?
Add mesh tutorials to the main tutorials branch #1908
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## doc/new-tutorials-section #1908 +/- ##
=============================================================
- Coverage 88.50% 88.37% -0.14%
=============================================================
Files 89 89
Lines 10251 10251
=============================================================
- Hits 9073 9059 -14
- Misses 1178 1192 +14 |
Could we restrict the |
|
|
Basically here the idea would be to show how to The next tutorial on |
Wouldn't this section be the Extract a mesh as split per body tutorial? |
12622e2
to
4f2323d
Compare
bd42cc2
to
47afb3b
Compare
doc/source/user_guide/tutorials/mesh/extract_mesh_in_split_parts.rst
Outdated
Show resolved
Hide resolved
576cd9f
to
627c2de
Compare
.. jupyter-execute:: | ||
|
||
# Import the ``ansys.dpf.core`` module | ||
from ansys.dpf import core as dpf | ||
# Import the examples module | ||
from ansys.dpf.core import examples | ||
# Import the operators module | ||
from ansys.dpf.core import operators as ops | ||
|
||
# Define the result file path | ||
result_file_path = examples.find_msup_transient() | ||
# Create the model | ||
model = dpf.Model(data_sources=result_file_path) |
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 would avoid combining comments and imports. Instead, I feel it is more appropriate to have paragraphs and small code cells:
.. jupyter-execute:: | |
# Import the ``ansys.dpf.core`` module | |
from ansys.dpf import core as dpf | |
# Import the examples module | |
from ansys.dpf.core import examples | |
# Import the operators module | |
from ansys.dpf.core import operators as ops | |
# Define the result file path | |
result_file_path = examples.find_msup_transient() | |
# Create the model | |
model = dpf.Model(data_sources=result_file_path) | |
Start by importing the `dpf`, `examples`, and `operators` modules: | |
.. jupyter-execute:: | |
from ansys.dpf import core as dpf | |
from ansys.dpf.core import examples | |
from ansys.dpf.core import operators as ops | |
Next, define the path to the result file and create the model: | |
.. jupyter-execute:: | |
result_file_path = examples.find_msup_transient() | |
model = dpf.Model(data_sources=result_file_path) |
.. note:: | ||
|
||
Only the |Elemental|, |Nodal|, or |Faces| locations are supported for animations. | ||
|Overall| and |ElementalNodal| locations are not currently supported. |
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 replacement is very convenient. I really like it.
:hide-code: | ||
:hide-output: | ||
|
||
disp_fc.animate(off_screen=True,save_as="source/user_guide/tutorials/animate/animate_disp_1.gif") |
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.
Not a big fan of storing output. It forces to manually regenerate it in the future and it is prone to get outdated quickly.
In the future, it would be great to migrate this to Jupytext. I bet that using MyST can provide us with the same tab-features we are using.
def search_sequence_numpy(arr, seq): | ||
"""Find a sequence in an array and return its index.""" | ||
indexes = np.where(np.isclose(arr, seq[0])) | ||
for index in np.nditer(indexes[0]): | ||
if index % 3 == 0: | ||
if np.allclose(arr[index + 1], seq[1]) and np.allclose(arr[index + 2], seq[2]): | ||
return index | ||
return -1 |
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 this should work too. It avoids using the np.nditer
function and handles dimensions before executing any logic:
def search_sequence_numpy(arr, seq): | |
"""Find a sequence in an array and return its index.""" | |
indexes = np.where(np.isclose(arr, seq[0])) | |
for index in np.nditer(indexes[0]): | |
if index % 3 == 0: | |
if np.allclose(arr[index + 1], seq[1]) and np.allclose(arr[index + 2], seq[2]): | |
return index | |
return -1 | |
if len(seq) == 0: | |
raise ValueError("The search sequence must not be empty.") | |
if len(seq) > len(arr): | |
return -1 # Sequence longer than the array cannot be found. | |
# Sliding window approach | |
for i in range(len(arr) - len(seq) + 1): | |
if np.allclose(arr[i:i + len(seq)], seq): | |
return i | |
return -1 |
…mesh operator on the split_mesh.rst tutorial
d11a84e
to
ae30d91
Compare
- Number of nodes and elements; | ||
- Unit; | ||
- Elements type. |
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.
Short lists should not end in periods or any other symbol:
- Number of nodes and elements; | |
- Unit; | |
- Elements type. | |
- Number of nodes and elements | |
- Unit | |
- Elements type |
- Number of nodes and elements; | ||
- Unit; | ||
- Elements type. |
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.
- Number of nodes and elements; | |
- Unit; | |
- Elements type. | |
- Number of nodes and elements | |
- Unit | |
- Elements type |
- Properties; | ||
- Parts; | ||
- Faces; | ||
- Bodies; | ||
- Zones; | ||
- Number of nodes and elements; | ||
- Elements types. |
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.
- Properties; | |
- Parts; | |
- Faces; | |
- Bodies; | |
- Zones; | |
- Number of nodes and elements; | |
- Elements types. | |
- Properties | |
- Parts | |
- Faces | |
- Bodies | |
- Zones | |
- Number of nodes and elements | |
- Elements types |
- Unit; | ||
- Nodes, elements and faces; | ||
- Named selections: . |
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.
- Unit; | |
- Nodes, elements and faces; | |
- Named selections: . | |
- Unit | |
- Nodes, elements and faces | |
- Named selections |
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.
Just left some additional comments on how to document list items.
.. |MeshesContainer| replace:: :class:`MeshesContainer <ansys.dpf.core.meshes_container.MeshesContainer>` | ||
.. |split_mesh| replace:: :class:`split_mesh <ansys.dpf.core.operators.mesh.split_mesh.split_mesh>` | ||
.. |split_on_property_type| replace:: :class:`split_on_property_type <ansys.dpf.core.operators.scoping.split_on_property_type.split_on_property_type>` | ||
.. |from_scopings| replace:: :class:`from_scopings <ansys.dpf.core.operators.mesh.from_scopings.from_scopings>` | ||
.. |ScopingsContainer| replace:: :class:`ScopingsContainer <ansys.dpf.core.scopings_container.ScopingsContainer>` | ||
.. |PropertyField| replace:: :class:`PropertyField <ansys.dpf.core.property_field.PropertyField>` |
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.
Great job Luisa! You made heavy use of substitution definitions which very nice.
I observed the following concerning these definitions:
- Some definitions already in links_and_refs.rst are being redefined, for example
|MeshesContainer|
and|ScopingsContainer|
. If definitions in links_and_refs.rst are changed in the future, the changes will not reflect in your examples because local definitions will take precedence. - You have same substitution definitions in more than one .rst file, for example
|meshes_provider|
common to get_mesh_from_result_file.rst and extract_mesh_in_split_parts.rst. If there is a restructuring of the dpf.core package in the future affecting the location|meshes_provider|
is pointing to, then each of the definitions in your examples have to be located and changed. It is a similar problem to that above.
The solution to this is to move all your substitution definitions to links_and_refs.rst. Then you have only one source of truth. Let me know what you think about the suggested approach.
def search_sequence_numpy(arr, seq): | ||
"""Find a sequence in an array and return its index.""" | ||
indexes = np.where(np.isclose(arr, seq[0])) | ||
for index in np.nditer(indexes[0]): | ||
if index % 3 == 0: | ||
if np.allclose(arr[index + 1], seq[1]) and np.allclose(arr[index + 2], seq[2]): | ||
return index | ||
return -1 |
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.
Great implementation and great suggestion by Jorge as well.
Numpy operations are multidimensional, and knowing how to take advantage of this will greatly simplify things. For example, you can directly determine the index of a node within a DPFArray of nodes as suggested below.
def search_sequence_numpy(arr, seq): | |
"""Find a sequence in an array and return its index.""" | |
indexes = np.where(np.isclose(arr, seq[0])) | |
for index in np.nditer(indexes[0]): | |
if index % 3 == 0: | |
if np.allclose(arr[index + 1], seq[1]) and np.allclose(arr[index + 2], seq[2]): | |
return index | |
return -1 | |
def search_sequence_numpy(arr, node): | |
"""Find the node location in an array of nodes and return its index.""" | |
indexes = np.isclose(arr, seq) | |
match = np.all(indexes, axis=1).nonzero() | |
return int(match[0][0]) |
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.
So this updated function will take my_nodes_coordinates_data
directly as input.
data_index = search_sequence_numpy(my_nodes_coordinates_data_list, [xx, yy, zz]) | ||
scoping_index = int(data_index / 3) # 3components |
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.
If you choose to go with the previous suggestion, then you just need to do this:
data_index = search_sequence_numpy(my_nodes_coordinates_data_list, [xx, yy, zz]) | |
scoping_index = int(data_index / 3) # 3components | |
scoping_index = search_sequence_numpy(my_nodes_coordinates_data, [xx, yy, zz]) |
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.
Of course, you would still need to take care of the suggestions already given by Jorge.
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.
Hi Luisa. Great work!
Going through the examples made me learn new things about DPF as working with DPF is also new for me... :)
I left a couple of comments. I will try to conduct more review when I am chanced.
Add new plot tutorials to the mesh section:
List of tutorials:
Preview on how it renders:
Mesh section main page
Create a mesh from scratch
Get a mesh from a result file
Read a mesh metadata
Explore a mesh
Extract a mesh in split parts
Split a mesh