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

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices #352

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

majosm
Copy link
Collaborator

@majosm majosm commented Oct 12, 2022

Now accepts a list of dicts (one per mesh group), where each dict maps a tag to a numpy array of element/face indices that belong to that tag. This removes the need to use Python loops over elements when generating and using the tag/face mappings.

…rtices

change the structure to something that can be constructed more efficiently
Copy link
Collaborator

@alexfikl alexfikl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just added some nitpicks, otherwise this looks good to me!

Any idea of how much faster this is compared to #350?

meshmode/mesh/__init__.py Outdated Show resolved Hide resolved
meshmode/mesh/__init__.py Outdated Show resolved Hide resolved
meshmode/mesh/generation.py Outdated Show resolved Hide resolved
@majosm
Copy link
Collaborator Author

majosm commented Oct 12, 2022

Any idea of how much faster this is compared to #350?

On my laptop, for a mesh with 1.2M elements:

main:

53.433 _get_box_mesh  poiseuille-mpi.py:74
└─ 53.420 inner_wrapper  pytools/__init__.py:243
   └─ 53.420 generate_regular_rect_mesh  meshmode/mesh/generation.py:1309
      └─ 53.417 inner_wrapper  pytools/__init__.py:243
            [2 frames hidden]  pytools
               53.393 generate_box_mesh  meshmode/mesh/generation.py:959
               ├─ 32.986 [self]  
               ├─ 5.383 <listcomp>  meshmode/mesh/generation.py:1228
               ├─ 3.608 <genexpr>  meshmode/mesh/generation.py:1262
               ├─ 2.667 __getattribute__  meshmode/mesh/__init__.py:279
               ├─ 1.440 _compute_facial_adjacency_from_vertices  meshmode/mesh/__init__.py:1400
               │  └─ 0.717 _match_faces_by_vertices  meshmode/mesh/__init__.py:1348
               ├─ 1.427 len  <built-in>:0
               │     [2 frames hidden]  <built-in>
               ├─ 1.342 list.index  <built-in>:0
               │     [2 frames hidden]  <built-in>
               ├─ 1.235 wrapper  pytools/__init__.py:752
               │     [4 frames hidden]  pytools, <built-in>
               ├─ 1.171 all  <built-in>:0
               │     [2 frames hidden]  <built-in>
               ├─ 0.995 __init__  meshmode/mesh/__init__.py:961
               │  └─ 0.797 _test_node_vertex_consistency  meshmode/mesh/__init__.py:1256
               │     └─ 0.775 _test_node_vertex_consistency_resampling  meshmode/mesh/__init__.py:1221
               └─ 0.606 inner_wrapper  pytools/__init__.py:243
                     [2 frames hidden]  pytools
                        0.595 make_group_from_vertices  meshmode/mesh/generation.py:340

optimize-tag-face-mapping:

5.350 _get_box_mesh  poiseuille-mpi.py:74
└─ 5.338 inner_wrapper  pytools/__init__.py:243
   └─ 5.338 generate_regular_rect_mesh  meshmode/mesh/generation.py:1308
      └─ 5.335 inner_wrapper  pytools/__init__.py:243
            [2 frames hidden]  pytools
               5.328 generate_box_mesh  meshmode/mesh/generation.py:959
               ├─ 1.793 [self]  
               ├─ 1.308 _compute_facial_adjacency_from_vertices  meshmode/mesh/__init__.py:1418
               │  ├─ 0.650 _match_faces_by_vertices  meshmode/mesh/__init__.py:1371
               │  │  ├─ 0.346 _find_matching_index_pairs_merged  meshmode/mesh/__init__.py:1348
               │  │  │  ├─ 0.160 lexsort  <__array_function__ internals>:177
               │  │  │  │     [3 frames hidden]  <__array_function__ internals>, <buil...
               │  │  │  ├─ 0.096 [self]  
               │  │  │  └─ 0.068 any  <__array_function__ internals>:177
               │  │  │        [5 frames hidden]  <__array_function__ internals>, numpy...
               │  │  ├─ 0.183 [self]  
               │  │  └─ 0.112 sort  <__array_function__ internals>:177
               │  │        [6 frames hidden]  <__array_function__ internals>, numpy...
               │  ├─ 0.259 lexsort  <__array_function__ internals>:177
               │  │     [3 frames hidden]  <__array_function__ internals>, <buil...
               │  ├─ 0.204 [self]  
               │  └─ 0.076 unique  <__array_function__ internals>:177
               │        [9 frames hidden]  <__array_function__ internals>, numpy...
               ├─ 0.902 __init__  meshmode/mesh/__init__.py:961
               │  ├─ 0.716 _test_node_vertex_consistency  meshmode/mesh/__init__.py:1256
               │  │  └─ 0.705 _test_node_vertex_consistency_resampling  meshmode/mesh/__init__.py:1221
               │  │     ├─ 0.339 amax  <__array_function__ internals>:177
               │  │     │     [5 frames hidden]  <__array_function__ internals>, numpy...
               │  │     ├─ 0.263 _mesh_group_node_vertex_error  meshmode/mesh/__init__.py:1202
               │  │     │  ├─ 0.140 [self]  
               │  │     │  └─ 0.122 einsum  <__array_function__ internals>:177
               │  │     │        [4 frames hidden]  <__array_function__ internals>, numpy...
               │  │     └─ 0.103 [self]  
               │  └─ 0.179 test_volume_mesh_element_orientations  meshmode/mesh/processing.py:637
               │     └─ 0.173 find_volume_mesh_element_orientations  meshmode/mesh/processing.py:603
               │        └─ 0.161 find_volume_mesh_element_group_orientation  meshmode/mesh/processing.py:553
               │           └─ 0.100 [self]  
               ├─ 0.611 inner_wrapper  pytools/__init__.py:243
               │     [2 frames hidden]  pytools
               │        0.603 make_group_from_vertices  meshmode/mesh/generation.py:340
               │        ├─ 0.402 einsum  <__array_function__ internals>:177
               │        │     [4 frames hidden]  <__array_function__ internals>, numpy...
               │        └─ 0.178 [self]  
               ├─ 0.303 unravel_index  <__array_function__ internals>:177
               │     [3 frames hidden]  <__array_function__ internals>, <buil...
               ├─ 0.194 stack  <__array_function__ internals>:177
               │     [5 frames hidden]  <__array_function__ internals>, numpy...
               └─ 0.186 all  <__array_function__ internals>:177
                     [5 frames hidden]  <__array_function__ internals>, numpy...

@majosm majosm marked this pull request as ready for review October 13, 2022 15:48
@majosm majosm requested a review from inducer October 13, 2022 15:48
Copy link
Owner

@inducer inducer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments from an initial scroll.

@@ -1345,6 +1345,29 @@ def _concatenate_face_ids(face_ids_list):
faces=np.concatenate([ids.faces for ids in face_ids_list]))


def _find_matching_index_pairs_merged(indices):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Describe shape of indices (and describe the axis along which the return value indexes).

return np.stack((order[match_indices], order[match_indices+1]))


def _find_matching_index_pairs(left_indices, right_indices):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Describe shape of left_indices and right_indices (and describe the axis along which indiex_pairs indexes).

Comment on lines 1426 to 1427
:class:`numpy.ndarray` of shape ``(2, nfaces)`` containing
the element and face indices of each tagged face in the group.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing you mean element indices in tag_to_group_faces[0] and face indices in tag_to_group_faces[1]? If so, say so.

"""
Return an array of dimension ``(2, nmatches)`` containing pairs of indices into
*indices* representing entries that are the same.
"""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document the interface consequences of lexsort being stable that are being used below.

"""
index_pairs = _find_matching_index_pairs_merged(
np.concatenate((left_indices, right_indices), axis=1))
index_pairs[1, :] -= left_indices.shape[1]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might it be worthwhile to assert that these are in range (i.e. not drawn into negative)?

face_index_pairs = _find_matching_index_pairs(
tagged_elements_and_faces.T,
np.stack((bdry_elements, bdry_element_faces)))
face_indices = face_index_pairs[1, :]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
face_indices = face_index_pairs[1, :]
bdry_face_indices = face_index_pairs[1, :]

is_tagged = np.full(len(bdry_elements), False)

for tag, tagged_elements_and_faces in tag_to_group_faces[igrp].items():
face_index_pairs = _find_matching_index_pairs(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
face_index_pairs = _find_matching_index_pairs(
vol_bdry_index_pairs = _find_matching_index_pairs(

Return an array containing pairs of indices into *indices* representing entries
that are the same.

Given an array *indices* of shape ``(N, nindices)`` containing integer-valued
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Given an array *indices* of shape ``(N, nindices)`` containing integer-valued
Given an array *indices* of shape ``(N, ntuples)`` containing integer-valued

Comment on lines +1358 to +1359
Returned matches are ordered such that the second element of the pair occurs
after the first in *indices*.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert (result[0] < result[1]).all()?

(Also improve phrasing here.)

# Indices into left_indices are the same as indices into all_indices, but need
# a conversion for right_indices
index_pairs[1, :] -= left_indices.shape[1]
assert index_pairs[1, :] >= 0 # Sanity check
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert index_pairs[1, :] >= 0 # Sanity check
assert (index_pairs[1, :] >= 0).all() # Sanity check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants