Skip to content

Long term dune growth (by Selwyn)#286

Open
Sierd wants to merge 5 commits intomainfrom
sed_supply_clean
Open

Long term dune growth (by Selwyn)#286
Sierd wants to merge 5 commits intomainfrom
sed_supply_clean

Conversation

@Sierd
Copy link
Collaborator

@Sierd Sierd commented Feb 19, 2026

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

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_reset with a more flexible wet_supply function 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
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on line 225 contains a typo. "seward" should be "seaward" (meaning toward the sea).

Copilot uses AI. Check for mistakes.
elev_dry = s['zb']>=s['TWL']

try:
if elev_dry[0][0] == True and s['TWL'][0][0] < p['veg_min_elevation']:
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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']:

Copilot uses AI. Check for mistakes.

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']:
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
beach_z = zb_all[xi]
x = x_all[xi]

xi3 = np.where(beach_z > p['zshoreline'])
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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

Copilot uses AI. Check for mistakes.
Comment on lines +212 to 232
# 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


Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
# 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

Copilot uses AI. Check for mistakes.
Comment on lines 234 to 248
@@ -219,19 +246,96 @@ def wet_bed_reset(s, p):
Spatial grids

'''
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
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
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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

Copilot uses AI. Check for mistakes.
<description>


longterm_dune_growth - 1D 27-year simulation from Long Beach Penninsula, Washington, USA (LBP)
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in the comment: "Penninsula" should be "Peninsula".

Suggested change
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)

Copilot uses AI. Check for mistakes.
Comment on lines +317 to +321
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]))
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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]))

Copilot uses AI. Check for mistakes.
Comment on lines +321 to +324
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]))
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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]))

Copilot uses AI. Check for mistakes.
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.

3 participants