Feature/thickness aware notches - #80
Conversation
|
All contributors have signed the CLA. Thank you! |
|
I have read the CLA Document and I hereby sign the CLA |
nicholas9182
left a comment
There was a problem hiding this comment.
Hi Kyle - great work!
The implementation is very clean.
My main thought is - at the moment the tabs are defined by their racetrack angle. I think they should instead be defined (at least the public APIs) by two variables:
1) the distance along the racetrack centre line
2) whether they are arranged transverse or longitudinal
in this way they become similar to the punched current collector designs. A key visualisation will then be the top-down view of the jelly roll, and seeing where the tabs end up sticking out. We should also add a limit to the position of the tabs so they cant sit on the curved part of the racetrack
| Function to calculate the positions of the tabs along the length of the current collector. | ||
| """ | ||
| x_min = self._datum[0] - self._x_foil_length / 2 | ||
|
|
There was a problem hiding this comment.
add a code comment here to explain what this bit is doing
There was a problem hiding this comment.
alternatively I would break this function out into two separate functions
def _calculate_explicit_tab_positions
def _calculate_regular_tab_positions
and then _calculate_tab_positions can just route to the right one depending
generally I am a fan of lots of small functions each with a dedicated purpose.
|
|
||
| self._tab_positions = np.column_stack((tab_starts, tab_ends)) | ||
|
|
||
| def _validate_tab_center_positions(self, positions: np.ndarray) -> None: |
There was a problem hiding this comment.
may be worth adding the word 'explicit' into the function name to convey that this is for when explicit tab positions are being used
| def tab_positions(self) -> list: | ||
| return [(start * M_TO_MM, end * M_TO_MM) for start, end in self._tab_positions] | ||
|
|
||
| @property |
| return (positions * M_TO_MM).tolist() | ||
|
|
||
| @property | ||
| def calculated_tab_center_positions(self) -> list: |
| return (centers * M_TO_MM).tolist() | ||
|
|
||
| @property | ||
| def tab_pitches(self) -> list: |
There was a problem hiding this comment.
I am a little unsure what 'pitches' refers too. Is it the spacing between the tabs?
|
|
||
| # get the thickness maximum bound | ||
| big_layup = deepcopy(self._layup) | ||
| self._clear_generated_notches_on_layup(big_layup) |
There was a problem hiding this comment.
I think these may be not-needed as the notch position shouldn't affect the jelly roll thickness. These are just used to get the upper and lower bound for the thickness value
| return self._pressed_straight_length * M_TO_MM | ||
|
|
||
| @property | ||
| def cathode_notch_alignment_angle(self) -> Optional[float]: |
There was a problem hiding this comment.
we can replace with cathode_notch_alignment_position
|
|
||
| @cathode_notch_alignment_angle.setter | ||
| @calculate_all_properties | ||
| def cathode_notch_alignment_angle(self, value: Optional[float]) -> None: |
| ) | ||
|
|
||
| @property | ||
| def anode_notch_alignment_angle(self) -> Optional[float]: |
There was a problem hiding this comment.
usually angles are returned through properties im degrees (as the human readable unit). We can add the radians-degrees converter to steer-core if not there already
There was a problem hiding this comment.
I think we're replacing the public angle API by a position in millimeters, so this becomes obsolete.
| @anode_notch_alignment_angle.setter | ||
| @calculate_all_properties | ||
| def anode_notch_alignment_angle(self, value: Optional[float]) -> None: | ||
| self._anode_notch_alignment_angle = self._validate_notch_alignment_angle( |
There was a problem hiding this comment.
the convention generally used throughout if for validating functions to return None. This would then become
self._validate_notch_alignment_angle(value, "anode_notch_alignment_angle")
self._anode_notch_alignment_angle = value
check elsewhere if changes need to be made
Summary
This PR adds opt-in, thickness-aware notch alignment for
FlatWoundJellyRoll.Previously,
NotchedCurrentCollectorused constant center-to-center tab spacing. After winding, however, outer racetrack layers have longer perimeters, causing tabs to progressively drift out of alignment.This change uses the calculated racetrack geometry to generate uneven tab positions along the unwrapped foil so that their centers align at the same racetrack phase after winding.
Below are example plots showing how tabs on cathode current collector align at the same phase after winding:



Design
The implementation follows the existing object responsibilities:
NotchedCurrentCollectorAdds support for explicit tab-center positions:
These positions are measured from the foil's leading edge and provide the low-level representation for non-uniform tab patterns.
Explicit positions are validated for ordering, overlap, and foil-boundary constraints. Setting
tab_spacingortab_gapreturns the collector to uniform-spacing mode.SpiralCalculatorAdds
aligned_positions_from_spiral(), which finds unwrapped foil positions satisfying:This ensures that generated tab centers share the same racetrack phase across successive wound layers while respecting tab-width and minimum-gap constraints.
FlatWoundJellyRollAdds independent cathode and anode alignment controls:
The jelly roll calculates the corresponding unwrapped tab-center positions from its wound geometry and applies them to the collectors.
Setting either alignment angle to
Nonerestores the existing uniform-spacing behavior for that electrode.Alignment Angle
The alignment angle represents a normalized phase around the racetrack perimeter rather than a literal geometric angle everywhere on the shape.
A phase difference of
2πcorresponds to one complete trip around the racetrack, so:identifies the same normalized racetrack phase on successive wound layers.
Because outer layers have longer perimeters, the resulting tab spacing on the unwrapped foil increases with winding radius.
Public API
New
NotchedCurrentCollectorinput:tab_center_positionsNew collector results:
calculated_tab_center_positionstab_pitchestab_gapsnumber_of_tabsNew
FlatWoundJellyRollinputs:cathode_notch_alignment_angleanode_notch_alignment_angleNew output and visualization:
thickness_aware_notch_dataplot_notch_alignment()Backward Compatibility
This feature is fully opt-in:
NotchedCurrentCollectorconstruction remains supported.tab_spacingremains the default.None.Testing
Added coverage for explicit tab-center patterns, validation, serialization, same-phase alignment, boundary handling, independent cathode/anode alignment, disabling alignment, and visualization.
Full test suite: