Implements Grid.compute_face_node_angles() - #1672
Conversation
This provides an initial implementation which seems to be working. See #1566 TODO: - support assume_convex=False - type-hint possible UxDataArray return type? - tests - examples
removes "geometry" (always use spherical) removes "assume_convex" (always assume convex) Also, improves type-hinting for compute_face_node_angles(). Also, formats using pre-commit ruff formatting.
use tuples instead of tiny arrays in numba! Cleans up docstring in grid.py (forgot to change in previous commit).
(it was making a type error in numba when trying to run the method)
compute_face_node_angles() seems to be really fast, so including a cache option in initial implementation isn't worthwhile.
ASV BenchmarkingBenchmark Comparison ResultsBenchmarks that have improved:
Benchmarks that have stayed the same:
|
|
Looks like this PR is having a nice side effect: the optimization to (The chain of calls is deep, so I'm putting it here for reference: Ignoring the apparent peakmem improvements (see #1605). Most importantly, none of the benchmarks show performance degradation, which helps demonstrate that the |
erogluorhan
left a comment
There was a problem hiding this comment.
This looks great to me! Thanks for all the invaluable discussion throughout this!
cmdupuis3
left a comment
There was a problem hiding this comment.
LGTM, tests pass and the tests and numba parallelization look reasonable. The vector arithmetic will probably need to sync up with other incoming PRs in the future though
Closes #1566
Overview
Implements new function:
Grid.compute_face_node_angles(), which computes the internal angles at each node, for each face in a grid. Intentionally excludes many options initially suggested in #1566, as the discussion there revealed:size=n_faces*n_max_face_nodes), so it doesn't really make sense to include a caching option right now.Also adds corresponding tests, checking that the angle computations give correct values in a roughly 30,60,90 degree triangle and a hexagon grid. Also checks nan handling in a grid with both pentagons and hexagons (result should be nan wherever
n_max_face_nodesdimension index is larger thann_nodes_per_face). For all three cases, checks that the generalized spherical excess formula holds, by comparing toGrid.face_areasresults.Within scope but possibly unexpected change included this PR: refactored
_small_angle_of_2_vectorsto improve efficiency when inputs are not numpy arrays, and rewrote docstring accordingly. (See also: #1648.) This was necessary to improve efficiency forcompute_face_node_angles()without inlining all of the_small_angle_of_2_vectorslogic. This is unlikely to affect efficiency elsewhere in the code, because other regions of the code seem to always construct tiny numpy arrays before calling_small_angle_of_2_vectors. Running ASV benchmarks here to check, just in case (but it would be acceptable if benchmarks show no improvements).Also related (may help visualize face node angle results, if implemented): #1578
Expected Usage
PR Checklist
General
Testing & Benchmarking
Documentation
docs/api.rst_)AI Disclosure
AI Usage: discussions with Claude and ChatGPT, inline code suggestions from GitHub Copilot. Also (not in this PR, but contributed to decisions, see original issue for details) used Claude to make a numpy-only method for efficiency comparisons, and other people used Claude to iterate and run tests for more efficiency improvements.