Feature: add neighbor subface helper#2216
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2216 +/- ##
==========================================
+ Coverage 78.27% 82.52% +4.24%
==========================================
Files 114 115 +1
Lines 19101 18561 -540
==========================================
+ Hits 14952 15318 +366
+ Misses 4149 3243 -906 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
spenke91
left a comment
There was a problem hiding this comment.
Thank you very much @dutkalex for another great contribution! :-) I am sorry it took us so long to reply...
I mostly have suggestions regarding variable names and code comments (which, I know, not everybody loves as much as I do 🤓 ). Aside from that, I only have a question regarding the hard-coded 4.
| t8_element_t *target = nullptr; | ||
| scheme->element_new (neighbor_tree_class, 1, &target); | ||
|
|
||
| int dummy; // Can't pass a nullptr to t8_forest_element_face_neighbor below (see #2214) | ||
| t8_forest_element_face_neighbor (forest, ltreeid, leaf, target, neighbor_tree_class, face, &dummy); |
There was a problem hiding this comment.
Maybe we can find a more expressive name than target? e.g.
| t8_element_t *target = nullptr; | |
| scheme->element_new (neighbor_tree_class, 1, &target); | |
| int dummy; // Can't pass a nullptr to t8_forest_element_face_neighbor below (see #2214) | |
| t8_forest_element_face_neighbor (forest, ltreeid, leaf, target, neighbor_tree_class, face, &dummy); | |
| // Determine the (virtual) face neighbor | |
| // Note: For this function to work properly, this face neighbor has to be a direct child of neighbor_leaf | |
| t8_element_t *virtual_face_neighbor= nullptr; | |
| scheme->element_new (neighbor_tree_class, 1, &virtual_face_neighbor); | |
| int dummy; // Can't pass a nullptr to t8_forest_element_face_neighbor below (see #2214) | |
| t8_forest_element_face_neighbor (forest, ltreeid, leaf, virtual_face_neighbor, neighbor_tree_class, face, &dummy); |
Or maybe we can even find something better? sub_neighbor?
There was a problem hiding this comment.
"There are only two hard things in computer science: cache invalidation and naming things." 😉
I see your point, and I guess since I could not come up with a better name at the time and went for the rather undescriptive but concise option. I feel like virtual_face_neighbor is more descriptive than sub_neighbor, but it looses the "it's what we're looking for" idea. It seems hard to find a (reasonably sized) name which encodes unambiguously all this information. Maybe this means a small comment is necessary to clarify exactly what this is... What do you think?
|
|
||
| scheme->element_get_children_at_face (neighbor_tree_class, neighbor_leaf, neighbor_face, children.begin (), | ||
| num_children, nullptr); | ||
|
|
There was a problem hiding this comment.
| Iterate over the neighbor's children and compare with virtual face neighbor to find the sub-face ID. |
There was a problem hiding this comment.
I guess this is meant to be a comment. However, after re-reading with fresh eyes this piece of code, I think this is just a std::find_if and that refactoring the code to use this is the proper way to make the intent explicit here
| result = i_child; | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
| // Free memory and return sub-face ID. |
There was a problem hiding this comment.
I think the "free memory" part is quite self evident here, but the "return sub-face ID" part is indeed not clear with the current state of the code. However maybe this just means that result is a bad name ? 😅
| int dummy; // Can't pass a nullptr to t8_forest_element_face_neighbor below (see #2214) | ||
| t8_forest_element_face_neighbor (forest, ltreeid, leaf, target, neighbor_tree_class, face, &dummy); | ||
|
|
||
| int const num_children = scheme->element_get_num_face_children (neighbor_tree_class, neighbor_leaf, neighbor_face); |
There was a problem hiding this comment.
| int const num_children = scheme->element_get_num_face_children (neighbor_tree_class, neighbor_leaf, neighbor_face); | |
| // Get the number of the neighbor's children touching the neighbor_face or, equivalenlty, the face's number of children. | |
| int const num_neighbor_face_children = scheme->element_get_num_face_children (neighbor_tree_class, neighbor_leaf, neighbor_face); |
There was a problem hiding this comment.
I can see why you'd want the variable name to be a little bit more explicit, but isn't the comment just paraphrasing what element_get_num_face_children's documentation already says?
I tend to think that comments should be used to explain why something is done a certain way, but not what the code does (that should be clear by reading the code, and if you think it's not the case maybe I should change the code then).
| std::array<t8_element_t *, 4> children; // assumes a 2:1 balanced forest | ||
| scheme->element_new (neighbor_tree_class, 4, children.begin ()); | ||
|
|
||
| scheme->element_get_children_at_face (neighbor_tree_class, neighbor_leaf, neighbor_face, children.begin (), | ||
| num_children, nullptr); |
There was a problem hiding this comment.
It may well be that I missed something here, but shouldn't we use num_face_children rather than 4?
| std::array<t8_element_t *, 4> children; // assumes a 2:1 balanced forest | |
| scheme->element_new (neighbor_tree_class, 4, children.begin ()); | |
| scheme->element_get_children_at_face (neighbor_tree_class, neighbor_leaf, neighbor_face, children.begin (), | |
| num_children, nullptr); | |
| // Create an array containing the neighbor's children at neighbor_face. | |
| std::array<t8_element_t *, num_neighbor_face_children> neighbor_children_at_face; | |
| scheme->element_new (neighbor_tree_class, num_neighbor_face_children, neighbor_children_at_face.begin ()); | |
| scheme->element_get_children_at_face (neighbor_tree_class, neighbor_leaf, neighbor_face, neighbor_children_at_face.begin (), num_neighbor_face_children, nullptr); |
There was a problem hiding this comment.
There are two reasons for why we can't use num_face_children/num_neighbor_face_children here:
- because we need an integral constant expression here (i.e. a
constexpr int-like thing) - because what we need here is the upper-bound of the number of face neighbors (this happens to be 4 for a 2:1 balanced interface) so that this piece of code works for any element type
Maybe there is a properly named global constant which could be used instead of this magic number?
| for (int i_child = 0; i_child < num_children; ++i_child) { | ||
| if (scheme->element_compare (neighbor_tree_class, target, children[i_child]) == 0) { |
There was a problem hiding this comment.
| for (int i_child = 0; i_child < num_children; ++i_child) { | |
| if (scheme->element_compare (neighbor_tree_class, target, children[i_child]) == 0) { | |
| for (int i_child = 0; i_child < num_neighbor_face_children; ++i_child) { | |
| if (scheme->element_compare (neighbor_tree_class, virtual_face_neighbor, neighbor_children_at_face[i_child]) == 0) { |
There was a problem hiding this comment.
I'll make the adequate changes here when the previous comments are settled.
Co-authored-by: spenke91 <thomas.spenke@dlr.de>
Add assertion to ensure the face was found before destruction.
No worries @spenke91. Thank you for taking the time, I know you guys have a lot on your plate.
I get it, I often say that getting the compiler to understand the code is the easy part and that the real challenge it to write code that humans can comprehend 😉. I have either committed your suggestions directly, or answered your comments/questions to get your opinion. Let me know what you think and I'll revise the code accordingly. |
Describe your changes here:
Implements #2215
All these boxes must be checked by the AUTHOR before requesting review:
Documentation:,Bugfix:,Feature:,Improvement:orOther:.All these boxes must be checked by the REVIEWERS before merging the pull request:
As a reviewer please read through all the code lines and make sure that the code is fully understood, bug free, well-documented and well-structured.
General
Tests
If the Pull request introduces code that is not covered by the github action (for example coupling with a new library):
Scripts and Wiki
scripts/internal/find_all_source_files.shto check the indentation of these files.License
doc/(or already has one).