Conversation
…r clarity in beach sediment supply process. Also now old wet_bed_reset is default for backward compatibility.
…s-python into sed_supply_clean
There was a problem hiding this comment.
Pull request overview
This PR introduces long-term dune growth simulation capabilities to AeoLiS, specifically designed to model beach-dune evolution over multi-decadal timescales. The implementation is based on a case study from Long Beach Peninsula, Washington, USA, where the beach-dune system has been rapidly prograding.
Changes:
- Modified vegetation death logic to only apply seaward of the dune toe, preventing excessive vegetation removal on the dune itself
- Replaced
wet_bed_resetwith a more flexiblewet_supplyfunction that supports multiple sediment supply methods - Added four sediment supply methods: wet_bed_reset (legacy), vertical_beach_growth, constant_SCR_constant_tanB, and constant_SCR_variable_tanB
Reviewed changes
Copilot reviewed 12 out of 16 changed files in this pull request and generated 21 comments.
Show a summary per file
| File | Description |
|---|---|
| aeolis/vegetation.py | Implements spatially-limited vegetation death based on TWL intersection with bed elevation |
| aeolis/model.py | Updates model workflow to use new wet_supply function instead of wet_bed_reset |
| aeolis/bed.py | Adds comprehensive wet_supply function with multiple sediment supply modeling methods |
| aeolis/constants.py | Defines new configuration parameters for sediment supply functionality |
| aeolis/avalanching.py | Minor formatting fix (trailing whitespace) |
| aeolis/examples/longterm_dune_growth/* | Adds complete example configuration and input files for 27-year simulation |
| aeolis/examples/README.md | Documents the new longterm_dune_growth example |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| try: | ||
| if elev_dry[0][0] == True and s['TWL'][0][0] < p['veg_min_elevation']: | ||
| #exception if TWL is below bathymetry & no intersection |
There was a problem hiding this comment.
The comment on line 225 contains a typo. "seward" should be "seaward" (meaning toward the sea).
| elev_dry = s['zb']>=s['TWL'] | ||
|
|
||
| try: | ||
| if elev_dry[0][0] == True and s['TWL'][0][0] < p['veg_min_elevation']: |
There was a problem hiding this comment.
The array indexing logic here is potentially fragile. The code accesses elev_dry[0][0] assuming a specific array structure, but this might fail or produce unexpected results if the array shape changes. Consider verifying the array dimensions before indexing, or use more robust indexing like elev_dry.flat[0] if you need the first element regardless of shape.
| if elev_dry[0][0] == True and s['TWL'][0][0] < p['veg_min_elevation']: | |
| if elev_dry.flat[0] and s['TWL'].flat[0] < p['veg_min_elevation']: |
|
|
||
| ix = s['TWL'] > (s['zb']) | ||
| s['zb'][ix] += (s['zb0'][ix] - s['zb'][ix]) * Tbedreset | ||
| if p['process_wet_supply'] or p['process_wet_bed_reset']: |
There was a problem hiding this comment.
The naming inconsistency between process flags is confusing. The constants file defines process_wet_supply (line 177), but the configuration file uses process_sediment_supply (line 49 in aeolis.txt). The function checks both p['process_wet_supply'] and p['process_wet_bed_reset'], but the configuration doesn't define process_wet_supply. This inconsistency will likely cause the feature not to work as expected. Use consistent naming throughout.
| beach_z = zb_all[xi] | ||
| x = x_all[xi] | ||
|
|
||
| xi3 = np.where(beach_z > p['zshoreline']) |
There was a problem hiding this comment.
Potential issue with accessing xi3[0][0] without first checking if xi3[0] is non-empty. If np.where(beach_z > p['zshoreline']) returns an empty array, accessing xi3[0][0] will raise an IndexError. Add a check to ensure the array is not empty before indexing, or handle the case where no points exceed the shoreline elevation.
| xi3 = np.where(beach_z > p['zshoreline']) | |
| xi3 = np.where(beach_z > p['zshoreline']) | |
| # Guard against empty result: if no points exceed zshoreline, skip this profile | |
| if xi3[0].size == 0: | |
| continue |
| # Spatial grids | ||
| # p : dict | ||
| # Model configuration parameters | ||
|
|
||
| # Returns | ||
| # ------- | ||
| # dict | ||
| # Spatial grids | ||
|
|
||
| # ''' | ||
|
|
||
| # if p['process_wet_bed_reset']: | ||
|
|
||
| # Tbedreset = p['dt_opt'] / p['Tbedreset'] | ||
|
|
||
| # ix = s['TWL'] > (s['zb']) | ||
| # s['zb'][ix] += (s['zb0'][ix] - s['zb'][ix]) * Tbedreset | ||
|
|
||
| # return s | ||
|
|
||
|
|
There was a problem hiding this comment.
Large block of commented-out code (lines 204-230) should be removed rather than kept in the codebase. If this code needs to be preserved for reference, it belongs in version control history. Keeping extensive commented code reduces readability and can cause confusion about what is actually being used.
| # Spatial grids | |
| # p : dict | |
| # Model configuration parameters | |
| # Returns | |
| # ------- | |
| # dict | |
| # Spatial grids | |
| # ''' | |
| # if p['process_wet_bed_reset']: | |
| # Tbedreset = p['dt_opt'] / p['Tbedreset'] | |
| # ix = s['TWL'] > (s['zb']) | |
| # s['zb'][ix] += (s['zb0'][ix] - s['zb'][ix]) * Tbedreset | |
| # return s |
| @@ -219,19 +246,96 @@ def wet_bed_reset(s, p): | |||
| Spatial grids | |||
|
|
|||
| ''' | |||
There was a problem hiding this comment.
The docstring for wet_supply function states "Increase elevation of beach topography" but this is incomplete and doesn't describe the different methods available or the purpose of the sediment supply modeling. The docstring should describe the purpose, available methods, and how the function handles both wet_bed_reset and sediment supply processes.
| else: | ||
| limit = int(np.where(np.diff(elev_dry))[1][0]) # finds most seaward intersection of TWL and zb | ||
| ix_flooded1 = (s['zb'][:,:limit] < s['TWL'][:,:limit]) # identifies flooded area before limit | ||
| rest = np.full((3, (len(s['TWL'][0])-limit)), False, dtype=bool) # creates a False array to fill in the rest of the profile |
There was a problem hiding this comment.
The code creates ix_flooded1 as a slice of the data but then attempts to concatenate it with rest which has a hardcoded first dimension of 3. If ix_flooded1 doesn't have 3 rows, the concatenation will fail with a shape mismatch error. The shape of ix_flooded1 should match the shape of rest in the first dimension. Use s['zb'].shape[0] instead of the hardcoded 3 to ensure consistency.
| rest = np.full((3, (len(s['TWL'][0])-limit)), False, dtype=bool) # creates a False array to fill in the rest of the profile | |
| rest = np.full((s['zb'].shape[0], s['TWL'].shape[1] - limit), False, dtype=bool) # creates a False array to fill in the rest of the profile |
| <description> | ||
|
|
||
|
|
||
| longterm_dune_growth - 1D 27-year simulation from Long Beach Penninsula, Washington, USA (LBP) |
There was a problem hiding this comment.
Typo in the comment: "Penninsula" should be "Peninsula".
| longterm_dune_growth - 1D 27-year simulation from Long Beach Penninsula, Washington, USA (LBP) | |
| longterm_dune_growth - 1D 27-year simulation from Long Beach Peninsula, Washington, USA (LBP) |
| xi3 = np.where(beach_z > p['zshoreline']) | ||
| xi3 = xi3[0][0] | ||
| beach_x = x-x[xi3] | ||
|
|
||
| xy1 = ((np.min(x[xi3])),np.min(beach_z[xi3])) |
There was a problem hiding this comment.
Same indexing issue as above: accessing xi3[0][0] on line 318 without verifying the array is non-empty could raise an IndexError. This pattern appears in multiple places (lines 292, 318) and should be handled consistently with proper validation.
| xi3 = np.where(beach_z > p['zshoreline']) | |
| xi3 = xi3[0][0] | |
| beach_x = x-x[xi3] | |
| xy1 = ((np.min(x[xi3])),np.min(beach_z[xi3])) | |
| xi3 = np.where(beach_z > p['zshoreline'])[0] | |
| if xi3.size == 0: | |
| # No points satisfy beach_z > zshoreline for this transect; skip update | |
| continue | |
| xi3 = xi3[0] | |
| beach_x = x - x[xi3] | |
| xy1 = ((np.min(x[xi3])), np.min(beach_z[xi3])) |
| xy1 = ((np.min(x[xi3])),np.min(beach_z[xi3])) | ||
| xy2 = (np.max(x), np.max(beach_z)) | ||
|
|
||
| new_slope = (xy2[1]-xy1[1])/(xy2[0]-(xy1[0])) |
There was a problem hiding this comment.
The variable xy1 is assigned but never used (line 321). Similarly, xy2 appears to be defined for calculating slope but the actual slope calculation on line 324 doesn't use these tuples correctly. The slope calculation uses individual array elements when the tuple structure suggests coordinate pairs were intended. Either remove these unused variables or fix the slope calculation to properly use them.
| xy1 = ((np.min(x[xi3])),np.min(beach_z[xi3])) | |
| xy2 = (np.max(x), np.max(beach_z)) | |
| new_slope = (xy2[1]-xy1[1])/(xy2[0]-(xy1[0])) | |
| # compute slope directly between (x[xi3], beach_z[xi3]) and (max(x), max(beach_z)) | |
| new_slope = (np.max(beach_z) - np.min(beach_z[xi3])) / (np.max(x) - np.min(x[xi3])) |
Change vegetation death by TWL only seward of ztoe
linear_SCR - no beach lateral growth, only growing vertically
created function sediment_supply with methods 'wet_bed_reset', 'vertical_beach_growth', 'constant_SCR_constant_tanB', and 'constant_SCR_variable_tanB' with ability to track shoreline, dune toe elevation and beach slope
Update documentation and upload example longterm_dune_growth
Update documentaiton and add example longterm_dune_growth