Uh oh!
There was an error while loading. Please reload this page.
Fix inconsistent out-of-range evaluation between Tabulated1D scalar and array paths - #4074
Conversation
Evaluating openmc.data.Tabulated1D on an array containing values outside the tabulated range returned zeros for those points, while scalar evaluation returns the value at the nearest tabulated endpoint. Assign boundary values to out-of-range points in the array evaluation path so that both paths agree. sum_functions is also updated to evaluate each tabulated component only where it is defined, which preserves the behavior of combined functions (e.g., fission energy release components) whose tabulated components cover different incident energy ranges. Fixes: openmc-dev#4041 Signed-off-by: Engineer <kawacukent@gmail.com>
CAOShurong
left a comment
There was a problem hiding this comment.
Context
Reviewed exact head b39ee90 against develop base 86ceaad.
Summary
The scalar/array boundary fix is useful and the new tests cover its intended interpolation behavior. I found one blocking dtype regression in sum_functions(), however: the new accumulator inherits an integer union-grid dtype and cannot add the floating-point values returned by supported functions.
Detailed findings
Blocking issue
- [Major] Please use an accumulator dtype compatible with the evaluated function values and add an integer-grid Tabulated1D + Polynomial regression. On the base, the supported combination returns [10.5, 20.0, 29.5] as float64; this head raises UFuncOutputCastingError while adding float64 into int64.
Verified areas
- Purpose/scope: focused fix for #4041, with no new dependency or public API.
- Correctness/testing: the 11 new tests pass locally; compileall and diff checking pass. The public rollup currently reports all 18 contexts successful.
- Physics/design/performance/docs: no new physics model or transport-loop allocation; the endpoint semantics are documented and the overall design remains localized.
I used AI assistance to help inspect the repository and run the base/head verification; I checked the exact diff, reproducer, and results before submitting this review.
| # Evaluate each function and add together. Tabulated functions are | ||
| # only evaluated where they are defined; values beyond a function's | ||
| # tabulated range do not contribute to the sum. | ||
| y = np.zeros_like(x) |
There was a problem hiding this comment.
np.zeros_like(x) inherits x's dtype. When a tabulated grid is integer-valued, y is int64, so adding a Polynomial (or any floating-point function result) raises UFuncOutputCastingError. This worked on develop and is used by supported sum_functions() call paths. Please initialize an accumulator that can safely represent the evaluated values and cover an integer-grid Tabulated1D + Polynomial case.
np.zeros_like(x) inherits the dtype of the union grid, so when the grid is integer-valued the accumulator cannot hold the floating-point results of combined functions such as Polynomial, raising UFuncTypeError. Initialize the accumulator with a float dtype, restored from the prior behavior of sum(f(x) for f in funcs) which promoted to float. Adds a regression test combining an integer-valued tabulated function with a polynomial (test_sum_functions_integer_grid). Co-authored-by: CAOShurong <notifications@github.com> Signed-off-by: Engineer <kawacukent@gmail.com>
kawacukennedy
commented
Aug 30, 2026
Thanks @CAOShurong for the careful review and for catching the dtype regression — that is exactly right. Reproduced: with an integer-valued grid, Fixed (commit 56a8e5a): the accumulator in Added regression test: The full |
Description
Evaluating
openmc.data.Tabulated1Don values outside its tabulated range currently gives different answers depending on whether the input is a scalar or an array:The scalar path (
_interpolate_scalar) returns the value at the nearest tabulated endpoint, while the array path in__call__initializes the output with zeros and only fills points that fall inside an interpolation region, leaving out-of-range entries at zero.This PR makes the array path assign the boundary values (
y[0]/y[-1]) to out-of-range points so that both paths agree. This is also consistent with the existing precision handling at the domain edges (np.isclosechecks), which already assigns endpoint values to near-edge points.Changes
openmc/data/function.py:Tabulated1D.__call__: out-of-range points now receive the value of the nearest tabulated endpoint, matching the scalar path.sum_functions: each tabulated component is now explicitly evaluated only where it is defined (points outside a component's own tabulated range contribute zero). This preserves the existing behavior of combined functions — e.g.,FissionEnergyRelease.recoverable,total, and theq_*properties, which combine components that may cover different incident energy ranges on a union grid — independently of the new out-of-range semantics.Testing
Added
tests/unit_tests/test_function.pycovering:sum_functionsbehavior for components with differing domains and for polynomial+tabulated combinations.Local results: all 11 new tests pass; existing unit tests that exercise these code paths were compared before/after the change with identical outcomes (failures observed locally are due to no nuclear data being configured and are present on unmodified
developas well).Fixes: #4041
Signed-off-by: Engineer kawacukent@gmail.com