Skip to content

Conversation

@FBumann
Copy link
Member

@FBumann FBumann commented Jan 17, 2026

Description

Brief description of the changes in this PR.

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Code refactoring

Related Issues

Closes #(issue number)

Testing

  • I have tested my changes
  • Existing tests still pass

Checklist

  • My code follows the project style
  • I have updated documentation if needed
  • I have added tests for new functionality (if applicable)

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed potential dimension-mismatch issues in bounds and constraint calculations for more reliable computations.
  • Refactor

    • Improved performance through optimized computation caching and enhanced dimension alignment in internal calculations.

✏️ Tip: You can customize this high-level summary in your review settings.

…that take bound tuples:

  1. basic_bounds - Added xr.broadcast(lower_bound, upper_bound)
  2. bounds_with_state - Added xr.broadcast(lower_bound, upper_bound)
  3. scaled_bounds - Added xr.broadcast(rel_lower, rel_upper)
  4. scaled_bounds_with_state - Added broadcasts for both relative_bounds and scaling_bounds tuples

  The state_transition_bounds and continuous_transition_bounds methods don't take bound tuples, so they don't need this fix.

  Summary of changes:
  - flixopt/modeling.py: Added xr.broadcast() calls in all four bounding methods to ensure bound pairs always have compatible dimensions
  - flixopt/components.py: Added xr.broadcast() at the end of _relative_charge_state_bounds (kept as defensive measure)

  This should handle all cases where a scalar bound (e.g., relative_minimum=0) is paired with a time-varying bound that may have additional dimensions like cluster.
  1. Added _xr_allclose() helper in modeling.py:79-95 - uses xarray operations that handle broadcasting natively:
  def _xr_allclose(a: xr.DataArray, b: xr.DataArray, atol: float = 1e-10) -> bool:
      diff = a - b  # xarray broadcasts automatically
      is_close = (abs(diff) <= atol) | (a.isnull() & b.isnull())
      return bool(is_close.all())
  2. Removed all xr.broadcast() calls from:
    - BoundingPatterns.basic_bounds
    - BoundingPatterns.bounds_with_state
    - BoundingPatterns.scaled_bounds
    - BoundingPatterns.scaled_bounds_with_state
    - StorageModel._relative_charge_state_bounds
  3. Replaced np.allclose() with _xr_allclose() in bounds_with_state and scaled_bounds

  The key insight: xarray arithmetic (a - b) handles broadcasting automatically, while np.allclose() does not. By using xarray operations for the comparison, we avoid the shape mismatch entirely without needing explicit broadcasts everywhere.
  - _relative_charge_state_bounds → broadcasts → used by _absolute_charge_state_bounds
  - relative_flow_rate_bounds → broadcasts → used by absolute_flow_rate_bounds

  So the downstream properties automatically get aligned data.

  Final architecture:
  1. Interface layer (the *_bounds properties) broadcasts once when returning tuples
  2. BoundingPatterns uses _xr_allclose which handles xarray operations gracefully (as safety net)
  3. No redundant broadcasting in constraint creation

  The _xr_allclose helper is still valuable as it's cleaner than np.allclose for xarray data and handles NaN correctly. It just won't need to do any broadcasting work now since inputs are pre-aligned.
  - 230 → 60 calls (one per element instead of 3-4 per element)
  - 74% reduction in broadcast overhead
  - ~12ms instead of ~45ms for a typical model
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 17, 2026

📝 Walkthrough

Walkthrough

This PR introduces performance optimizations and improves dimensional consistency across xarray operations. Three property methods are converted to cached_properties to avoid recomputation, explicit broadcasting via xr.broadcast() is added to ensure matching dimensions, and a new helper function _xr_allclose() is introduced for xarray-aware element-wise comparison.

Changes

Cohort / File(s) Summary
Property Caching & Broadcasting
flixopt/components.py, flixopt/elements.py
Converted _relative_charge_state_bounds and relative_flow_rate_bounds from @property to @functools.cached_property to cache computed values. Updated return statements to use xr.broadcast() for matching dimensions across min/max bounds. Added import functools.
Array Comparison Utility
flixopt/modeling.py
Introduced _xr_allclose() helper function to compare xarray DataArrays with configurable tolerance (rtol=1e-5, atol=1e-8). Updated bounds_with_state() and scaled_bounds() to use this new helper instead of direct numpy.allclose() calls.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

v3.0.0

Poem

🐰 Cache the bounds, no second hop,
Broadcast dimensions, mismatches stop!
New helper functions compare with flair,
Making optimization light as the air! ⚡

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is entirely a template skeleton with no actual narrative content explaining the changes, objectives, or rationale. Fill in the Description section with a clear explanation of what was changed and why, specify the Type of Change, reference related issues if applicable, and check appropriate testing boxes.
Title check ❓ Inconclusive The title 'Fix/broadcasting' is vague and uses generic phrasing that does not clearly convey the specific changes made in the changeset. Replace with a more descriptive title that specifically explains the fix, such as 'Add xr.broadcast and caching to fix dimension mismatches in bounds' or 'Use cached_property with broadcasting for bounds calculations'.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 90.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@FBumann
Copy link
Member Author

FBumann commented Jan 17, 2026

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 17, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@FBumann FBumann merged commit efd91f5 into feature/tsam-v3+rework Jan 17, 2026
8 checks passed
Sign up for free to 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.

2 participants