First pass at EFT-based spherical geometry accuracy (port from AccuSphGeom)#1513
First pass at EFT-based spherical geometry accuracy (port from AccuSphGeom)#1513rajeeja wants to merge 4 commits into
Conversation
|
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
There was a problem hiding this comment.
We have an existed implementation for these functions in
uxarray/uxarray/utils/computing.py
Line 189 in 735a1dd
And I would suggest use other name instead of eft here, the term "EFT" specifically refers to "Error-Free" floating point operations, but the AccuCross and diff_of_productthemself is not completely Error-Free, is just more accurate than normal floating point cross (doubling the precision)
|
|
||
|
|
||
| @njit(cache=True) | ||
| def _generate_lat_lon_bounds_local(face_vertices, z_min, z_max, snap_tol_deg): |
There was a problem hiding this comment.
For a better vectorization, consider keeping the current design in https://github.com/hongyuchen1030/AccuSphGeom/blob/56cbd6e30270ec5845a853ec72ba5b19c9128017/include/accusphgeom/algorithms/lat_lon_bounds.hpp#L107:
It uses lots of masking and avoid branching for computation steps.
|
|
||
|
|
||
| @njit(cache=True) | ||
| def _generate_lat_lon_bounds_pole(face_vertices, label, z_min, z_max, snap_tol_deg): |
There was a problem hiding this comment.
Same here, consider keeping the structure here: https://github.com/hongyuchen1030/AccuSphGeom/blob/56cbd6e30270ec5845a853ec72ba5b19c9128017/include/accusphgeom/algorithms/lat_lon_bounds.hpp#L159
use masks instead of branching as much as possible for the vectorization purpose
|
|
||
|
|
||
| @njit(cache=True) | ||
| def _face_location_info(face_vertices, polar_cap_z): |
There was a problem hiding this comment.
The branching here will probably slow down the vectorization, consider keeping the structure here:
https://github.com/hongyuchen1030/AccuSphGeom/blob/56cbd6e30270ec5845a853ec72ba5b19c9128017/include/accusphgeom/algorithms/lat_lon_bounds.hpp#L49
| @njit(cache=True) | ||
| def _normalize_pair(x_hi, y_hi, z_hi, x_lo, y_lo, z_lo): | ||
| """Normalize an (hi, lo) compensated vector, returning the unit vector and magnitude.""" | ||
| x = x_hi + x_lo |
There was a problem hiding this comment.
This _normalize_pair is not utilizing the EFT and it will have the same precision as the direct floating point precision. And the normalization is one of the big killer for the precision.
There was a problem hiding this comment.
Also if the input are normalized, then both the gca_gca_intersection and the gca_constLat_intersection will return the normalized results already
There was a problem hiding this comment.
And just in case you want an "accurately calculated norm", it is const auto sum = numeric::sum_of_squares_c<T, 3>(v.hi, v.lo); const auto norm = numeric::acc_sqrt_re(sum.hi, sum.lo);
| @@ -301,139 +314,198 @@ def _gca_gca_intersection_cartesian(gca_a_xyz, gca_b_xyz): | |||
|
|
|||
| @njit(cache=True) | |||
There was a problem hiding this comment.
consider keeping the entire structure from here : https://github.com/hongyuchen1030/AccuSphGeom/blob/e4e13215dd4771b7ef01b7edf81eaf58dd6e6995/include/accusphgeom/constructions/gca_gca_intersection.hpp#L31
These EFT-fused operations are extremely sensitive for each operations and order. The accuracy can only be guaranteed iff following the exact algorithm
|
|
||
|
|
||
| @njit(cache=True) | ||
| def gca_const_lat_intersection(gca_cart, const_z): |
There was a problem hiding this comment.
The algorithm is almost very stable around floating point precision. Within the current Uxarray Error tolerance, you almost don't have to use any other safety pre-check other than if the input are valid (The relative error bound is 3*\sqrt{1-constz^2}*machine_epsilon as long as it's constZ is at least 10^15 from the equator) . And probably the only check needed Then only check you can make is if the const latitude is at the equator . Again, make sure to follow the entire algorithm structure from below. Such precision is only guaranteed
iff it follows the exact algorithm here
https://github.com/hongyuchen1030/AccuSphGeom/blob/e4e13215dd4771b7ef01b7edf81eaf58dd6e6995/include/accusphgeom/constructions/gca_constlat_intersection.hpp#L33
There was a problem hiding this comment.
But you can use the same check as in https://github.com/hongyuchen1030/AccuSphGeom/blob/e4e13215dd4771b7ef01b7edf81eaf58dd6e6995/include/accusphgeom/constructions/gca_gca_intersection.hpp#L51
to remove any invalid points
| nx = nx_hi + nx_lo | ||
| ny = ny_hi + ny_lo | ||
| nz = nz_hi + nz_lo | ||
| denom = nx * nx + ny * ny |
There was a problem hiding this comment.
Denome should be calculated from
const T denom = s2.hi + s2.lo;
where
const auto s2 = numeric::sum_of_squares_c<T, 2>( {normal.hi[0], normal.hi[1]}, {normal.lo[0], normal.lo[1]});
| @@ -301,139 +314,198 @@ def _gca_gca_intersection_cartesian(gca_a_xyz, gca_b_xyz): | |||
|
|
|||
| @njit(cache=True) | |||
| def gca_gca_intersection(gca_a_xyz, gca_b_xyz): | |||
There was a problem hiding this comment.
Consider keeping the entire structure from here https://github.com/hongyuchen1030/AccuSphGeom/blob/e4e13215dd4771b7ef01b7edf81eaf58dd6e6995/include/accusphgeom/constructions/gca_gca_intersection.hpp#L31.
These algorithms are extremely sensitive to the operations and order, the accuracy is only guaranteed iff we follow the exact same algorithm described
| x2_at_const_z = np.isclose( | ||
| x2[2], const_z, rtol=ERROR_TOLERANCE, atol=ERROR_TOLERANCE | ||
| ) | ||
| # 1. Endpoint coincidence with the latitude line. |
There was a problem hiding this comment.
This case is still valid and calculable with the new algorithm. And we can improve the vectorization by only use mask-selection after the intersection is calculated to snap the intersection point with the endpoints
| z_max = extreme_gca_z(gca_cart, extreme_type="max") | ||
|
|
||
| # Check if the constant latitude is within the GCA range | ||
| if not in_between(z_min, const_z, z_max): |
There was a problem hiding this comment.
I am not sure if this early exist will counter-effect the branching it brings to the vectorization
| elif p2_intersects_gca: | ||
| res[0] = p2 | ||
| # 4. Solve for the two candidate points on the latitude circle. | ||
| r2 = 1.0 - const_z * const_z |
There was a problem hiding this comment.
This is not the new EFT-fused algorithmn
|
@hongyuchen1030 Thanks for the review. The point-in-polygon predicate and
|
Closes #1509
Ports EFT primitives from AccuSphGeom (Chen 2026) into
uxarray/grid/_eft.pyand replaces naive cross-product arithmetic inarcs.py,intersections.py,bounds.py, andpoint_in_face.pywith EFT-backedorient3d_on_sphereandon_minor_arc. Adds a user guide notebook covering the problem, API, and a live point-in-polygon demo.