Change tag/face mapping argument of _compute_facial_adjacency_from_vertices - #352

Open
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping
Open

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices#352
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping

Conversation

@majosm

Copy link
Copy Markdown
Collaborator

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

@alexfiklalexfikl left a comment

Copy link
Copy Markdown
Collaborator

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?

Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/generation.py Outdated
majosmand others added 3 commits October 12, 2022 17:04
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from 8c3430a to db96dcaCompareOctober 12, 2022 22:12
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from db96dca to 65f7f01CompareOctober 12, 2022 22:14
@majosm

Copy link
Copy Markdown
CollaboratorAuthor

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 inducerOctober 13, 2022 15:48

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

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.

faces=np.concatenate([ids.faces for ids in face_ids_list]))


def _find_matching_index_pairs_merged(indices):

Copy link
Copy Markdown
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
Copy Markdown
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 threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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)?

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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, :]

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
Givenanarray*indices*ofshape``(N, nindices)``containinginteger-valued
Givenanarray*indices*ofshape``(N, ntuples)``containinginteger-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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

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

@majosmmajosm mentioned this pull request May 2, 2025
2 tasks
Sign up for freeto 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.

3 participants

@majosm@inducer@alexfikl
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices - #352

Open
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping
Open

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices#352
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping

Conversation

@majosm

Copy link
Copy Markdown
Collaborator

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

@alexfiklalexfikl left a comment

Copy link
Copy Markdown
Collaborator

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?

Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/generation.py Outdated
majosmand others added 3 commits October 12, 2022 17:04
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from 8c3430a to db96dcaCompareOctober 12, 2022 22:12
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from db96dca to 65f7f01CompareOctober 12, 2022 22:14
@majosm

Copy link
Copy Markdown
CollaboratorAuthor

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 inducerOctober 13, 2022 15:48

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

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.

faces=np.concatenate([ids.faces for ids in face_ids_list]))


def _find_matching_index_pairs_merged(indices):

Copy link
Copy Markdown
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
Copy Markdown
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 threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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)?

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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, :]

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
Givenanarray*indices*ofshape``(N, nindices)``containinginteger-valued
Givenanarray*indices*ofshape``(N, ntuples)``containinginteger-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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

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

@majosmmajosm mentioned this pull request May 2, 2025
2 tasks
Sign up for freeto 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.

3 participants

@majosm@inducer@alexfikl
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices - #352

Open
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping
Open

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices#352
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping

Conversation

@majosm

Copy link
Copy Markdown
Collaborator

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

@alexfiklalexfikl left a comment

Copy link
Copy Markdown
Collaborator

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?

Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/generation.py Outdated
majosmand others added 3 commits October 12, 2022 17:04
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from 8c3430a to db96dcaCompareOctober 12, 2022 22:12
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from db96dca to 65f7f01CompareOctober 12, 2022 22:14
@majosm

Copy link
Copy Markdown
CollaboratorAuthor

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 inducerOctober 13, 2022 15:48

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

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.

faces=np.concatenate([ids.faces for ids in face_ids_list]))


def _find_matching_index_pairs_merged(indices):

Copy link
Copy Markdown
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
Copy Markdown
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 threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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)?

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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, :]

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
Givenanarray*indices*ofshape``(N, nindices)``containinginteger-valued
Givenanarray*indices*ofshape``(N, ntuples)``containinginteger-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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

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

@majosmmajosm mentioned this pull request May 2, 2025
2 tasks
Sign up for freeto 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.

3 participants

@majosm@inducer@alexfikl
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices - #352

Open
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping
Open

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices#352
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping

Conversation

@majosm

Copy link
Copy Markdown
Collaborator

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

@alexfiklalexfikl left a comment

Copy link
Copy Markdown
Collaborator

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?

Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/generation.py Outdated
majosmand others added 3 commits October 12, 2022 17:04
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from 8c3430a to db96dcaCompareOctober 12, 2022 22:12
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from db96dca to 65f7f01CompareOctober 12, 2022 22:14
@majosm

Copy link
Copy Markdown
CollaboratorAuthor

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 inducerOctober 13, 2022 15:48

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

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.

faces=np.concatenate([ids.faces for ids in face_ids_list]))


def _find_matching_index_pairs_merged(indices):

Copy link
Copy Markdown
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
Copy Markdown
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 threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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)?

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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, :]

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
Givenanarray*indices*ofshape``(N, nindices)``containinginteger-valued
Givenanarray*indices*ofshape``(N, ntuples)``containinginteger-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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

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

@majosmmajosm mentioned this pull request May 2, 2025
2 tasks
Sign up for freeto 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.

3 participants

@majosm@inducer@alexfikl
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices - #352

Open
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping
Open

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices#352
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping

Conversation

@majosm

Copy link
Copy Markdown
Collaborator

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

@alexfiklalexfikl left a comment

Copy link
Copy Markdown
Collaborator

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?

Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/generation.py Outdated
majosmand others added 3 commits October 12, 2022 17:04
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from 8c3430a to db96dcaCompareOctober 12, 2022 22:12
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from db96dca to 65f7f01CompareOctober 12, 2022 22:14
@majosm

Copy link
Copy Markdown
CollaboratorAuthor

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 inducerOctober 13, 2022 15:48

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

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.

faces=np.concatenate([ids.faces for ids in face_ids_list]))


def _find_matching_index_pairs_merged(indices):

Copy link
Copy Markdown
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
Copy Markdown
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 threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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)?

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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, :]

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
Givenanarray*indices*ofshape``(N, nindices)``containinginteger-valued
Givenanarray*indices*ofshape``(N, ntuples)``containinginteger-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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

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

@majosmmajosm mentioned this pull request May 2, 2025
2 tasks
Sign up for freeto 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.

3 participants

@majosm@inducer@alexfikl
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices - #352

Open
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping
Open

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices#352
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping

Conversation

@majosm

Copy link
Copy Markdown
Collaborator

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

@alexfiklalexfikl left a comment

Copy link
Copy Markdown
Collaborator

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?

Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/generation.py Outdated
majosmand others added 3 commits October 12, 2022 17:04
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from 8c3430a to db96dcaCompareOctober 12, 2022 22:12
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from db96dca to 65f7f01CompareOctober 12, 2022 22:14
@majosm

Copy link
Copy Markdown
CollaboratorAuthor

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 inducerOctober 13, 2022 15:48

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

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.

faces=np.concatenate([ids.faces for ids in face_ids_list]))


def _find_matching_index_pairs_merged(indices):

Copy link
Copy Markdown
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
Copy Markdown
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 threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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)?

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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, :]

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
Givenanarray*indices*ofshape``(N, nindices)``containinginteger-valued
Givenanarray*indices*ofshape``(N, ntuples)``containinginteger-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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

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

@majosmmajosm mentioned this pull request May 2, 2025
2 tasks
Sign up for freeto 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.

3 participants

@majosm@inducer@alexfikl
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices - #352

Open
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping
Open

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices#352
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping

Conversation

@majosm

Copy link
Copy Markdown
Collaborator

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

@alexfiklalexfikl left a comment

Copy link
Copy Markdown
Collaborator

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?

Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/generation.py Outdated
majosmand others added 3 commits October 12, 2022 17:04
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from 8c3430a to db96dcaCompareOctober 12, 2022 22:12
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from db96dca to 65f7f01CompareOctober 12, 2022 22:14
@majosm

Copy link
Copy Markdown
CollaboratorAuthor

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 inducerOctober 13, 2022 15:48

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

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.

faces=np.concatenate([ids.faces for ids in face_ids_list]))


def _find_matching_index_pairs_merged(indices):

Copy link
Copy Markdown
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
Copy Markdown
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 threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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)?

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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, :]

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
Givenanarray*indices*ofshape``(N, nindices)``containinginteger-valued
Givenanarray*indices*ofshape``(N, ntuples)``containinginteger-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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

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

@majosmmajosm mentioned this pull request May 2, 2025
2 tasks
Sign up for freeto 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.

3 participants

@majosm@inducer@alexfikl
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices - #352

Open
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping
Open

Change tag/face mapping argument of _compute_facial_adjacency_from_vertices#352
majosm wants to merge 10 commits into
inducer:mainfrom
majosm:optimize-tag-face-mapping

Conversation

@majosm

Copy link
Copy Markdown
Collaborator

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

@alexfiklalexfikl left a comment

Copy link
Copy Markdown
Collaborator

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?

Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/__init__.py Outdated
Comment threadmeshmode/mesh/generation.py Outdated
majosmand others added 3 commits October 12, 2022 17:04
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
Co-authored-by: Alex Fikl <alexfikl@gmail.com>
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from 8c3430a to db96dcaCompareOctober 12, 2022 22:12
@majosm
majosmforce-pushed the optimize-tag-face-mapping branch from db96dca to 65f7f01CompareOctober 12, 2022 22:14
@majosm

Copy link
Copy Markdown
CollaboratorAuthor

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 inducerOctober 13, 2022 15:48

@inducerinducer left a comment

Copy link
Copy Markdown
Owner

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.

faces=np.concatenate([ids.faces for ids in face_ids_list]))


def _find_matching_index_pairs_merged(indices):

Copy link
Copy Markdown
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
Copy Markdown
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 threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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)?

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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, :]

Comment threadmeshmode/mesh/__init__.py Outdated
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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
Givenanarray*indices*ofshape``(N, nindices)``containinginteger-valued
Givenanarray*indices*ofshape``(N, ntuples)``containinginteger-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
Copy Markdown
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
Copy Markdown
Owner

Choose a reason for hiding this comment

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

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

@majosmmajosm mentioned this pull request May 2, 2025
2 tasks
Sign up for freeto 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.

3 participants

@majosm@inducer@alexfikl