Skip to content

Conversation

@Sierd
Copy link
Collaborator

@Sierd Sierd commented Oct 23, 2025

Code still needs to be tested. Especially the NE_layer.

Also, 1D compatibility needs to be tested.

Sierd added 2 commits October 23, 2025 19:38
Tested for 2D cases, seems to work fine now.
Need to test for 1D cases.
@Sierd Sierd requested a review from Copilot October 23, 2025 23:45
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 refactors the avalanching module to use Numba's JIT compilation for performance optimization. The main change extracts the iterative avalanche computation into a separate @njit-decorated function that uses explicit loops instead of NumPy boolean indexing, which is more compatible with Numba.

Key changes:

  • Extracted avalanche iteration logic into a Numba-compiled avalanche_loop function
  • Simplified flux computation from 4-directional to 2-directional (X and Y only)
  • Modified parameter E from 0.2 to 0.1

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines 194 to 198
# grad_h_nonerod = (zb[i, j] - zne[i, j]) / (ds[i, j]*dn[i, j])
if grad_h[i, j] > tan_dyn: # and (zb[i, j] - zne[i, j]) > 0.0:
slope_diff[i, j] = np.tanh(grad_h[i, j]) - np.tanh(0.9 * tan_dyn)
# elif grad_h_nonerod < (grad_h[i, j] - tan_dyn):
# slope_diff[i, j] = np.tanh(grad_h_nonerod)
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

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

Commented-out conditions suggest incomplete implementation. The original code had logic to handle grad_h_nonerod when it was less than grad_h - tan_dyn (lines 197-198 also commented). These conditions should either be properly implemented or removed with explanation in commit message if intentionally excluded.

Suggested change
# grad_h_nonerod = (zb[i, j] - zne[i, j]) / (ds[i, j]*dn[i, j])
if grad_h[i, j] > tan_dyn: # and (zb[i, j] - zne[i, j]) > 0.0:
slope_diff[i, j] = np.tanh(grad_h[i, j]) - np.tanh(0.9 * tan_dyn)
# elif grad_h_nonerod < (grad_h[i, j] - tan_dyn):
# slope_diff[i, j] = np.tanh(grad_h_nonerod)
# Only the main slope condition is currently implemented.
# Handling for non-erodible gradients (grad_h_nonerod) is not included.
if grad_h[i, j] > tan_dyn:
slope_diff[i, j] = np.tanh(grad_h[i, j]) - np.tanh(0.9 * tan_dyn)

Copilot uses AI. Check for mistakes.
Comment on lines 203 to 204
flux_down[i, j, 0] = slope_diff[i, j] * grad_h_down[i, j, 0]# / grad_h[i, j]
flux_down[i, j, 1] = slope_diff[i, j] * grad_h_down[i, j, 1]# / grad_h[i, j]
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

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

The division by grad_h[i, j] is commented out, changing the flux calculation significantly from the original implementation. The original code normalized flux components by the total gradient magnitude. This change should be documented as it affects the physical behavior of the avalanching model.

Suggested change
flux_down[i, j, 0] = slope_diff[i, j] * grad_h_down[i, j, 0]# / grad_h[i, j]
flux_down[i, j, 1] = slope_diff[i, j] * grad_h_down[i, j, 1]# / grad_h[i, j]
flux_down[i, j, 0] = slope_diff[i, j] * grad_h_down[i, j, 0] / grad_h[i, j]
flux_down[i, j, 1] = slope_diff[i, j] * grad_h_down[i, j, 1] / grad_h[i, j]

Copilot uses AI. Check for mistakes.
Comment on lines 243 to 250
if np.any((E * (q_in - q_out)) < (zne-zb)):
# update bed level with non-erodible layer limit
# this will effectively shut down further avalanching from the cells concerned
# because zb will equal zne there in the next iteration
zb += (zne - zb)
else:
# update bed level without non-erodible layer
zb += E * (q_in - q_out)
Copy link

Copilot AI Oct 23, 2025

Choose a reason for hiding this comment

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

This unconditionally sets zb = zne for all cells when any cell violates the non-erodible layer condition. This is incorrect - only cells where zb + E * (q_in - q_out) < zne[i, j] should be limited to zne[i, j]. The update should be element-wise with proper masking or a per-cell conditional.

Suggested change
if np.any((E * (q_in - q_out)) < (zne-zb)):
# update bed level with non-erodible layer limit
# this will effectively shut down further avalanching from the cells concerned
# because zb will equal zne there in the next iteration
zb += (zne - zb)
else:
# update bed level without non-erodible layer
zb += E * (q_in - q_out)
# Compute proposed new bed level
zb_new = zb + E * (q_in - q_out)
# Mask for cells where new bed level would fall below non-erodible layer
mask = zb_new < zne
# For masked cells, set zb to zne; otherwise, apply normal update
zb[mask] = zne[mask]
zb[~mask] = zb_new[~mask]

Copilot uses AI. Check for mistakes.
Sierd and others added 7 commits October 25, 2025 10:40
copilot suggested changes on memory allocation

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
added boundary definition.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
copilot suggestion to filter for ne

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Removed requirement for ne_file when avalanching is enabled
@Sierd Sierd requested a review from Copilot October 25, 2025 10:30
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

Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 182 to 189
# for i in range(ny):
# for j in range(nx):
# grad_h_down[i, j, 0] = grad_h_down[i, j, 0] / ds[i, j]
# grad_h_down[i, j, 1] = grad_h_down[i, j, 1] / dn[i, j]

# gradient magnitude and maximum
# for i in range(ny):
# for j in range(nx):
Copy link

Copilot AI Oct 25, 2025

Choose a reason for hiding this comment

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

Large blocks of commented-out code should be removed. The normalization by grid spacing is already performed inline at lines 165 and 179, making this commented block redundant. If this alternative approach is needed for reference, it should be documented in version control history instead.

Suggested change
# for i in range(ny):
# for j in range(nx):
# grad_h_down[i, j, 0] = grad_h_down[i, j, 0] / ds[i, j]
# grad_h_down[i, j, 1] = grad_h_down[i, j, 1] / dn[i, j]
# gradient magnitude and maximum
# for i in range(ny):
# for j in range(nx):
# gradient magnitude and maximum

Copilot uses AI. Check for mistakes.
Comment on lines 210 to 213
if grad_h[i, j] > tan_dyn: # and (zb[i, j] - zne[i, j]) > 0.0:
slope_diff[i, j] = np.tanh(grad_h[i, j]) - np.tanh(0.9 * tan_dyn)
# elif grad_h_nonerod < (grad_h[i, j] - tan_dyn):
# slope_diff[i, j] = np.tanh(grad_h_nonerod)
Copy link

Copilot AI Oct 25, 2025

Choose a reason for hiding this comment

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

Commented-out conditions and alternative logic should either be implemented or removed. The partial condition # and (zb[i, j] - zne[i, j]) > 0.0 and the entire elif block (lines 212-213) suggest incomplete implementation. Either complete this logic or remove the comments if the simplified version is intended.

Suggested change
if grad_h[i, j] > tan_dyn: # and (zb[i, j] - zne[i, j]) > 0.0:
slope_diff[i, j] = np.tanh(grad_h[i, j]) - np.tanh(0.9 * tan_dyn)
# elif grad_h_nonerod < (grad_h[i, j] - tan_dyn):
# slope_diff[i, j] = np.tanh(grad_h_nonerod)
if grad_h[i, j] > tan_dyn:
slope_diff[i, j] = np.tanh(grad_h[i, j]) - np.tanh(0.9 * tan_dyn)

Copilot uses AI. Check for mistakes.
Comment on lines 218 to 219
flux_down[i, j, 0] = slope_diff[i, j] * grad_h_down[i, j, 0]# / grad_h[i, j]
flux_down[i, j, 1] = slope_diff[i, j] * grad_h_down[i, j, 1]# / grad_h[i, j]
Copy link

Copilot AI Oct 25, 2025

Choose a reason for hiding this comment

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

The commented-out division by grad_h[i, j] suggests uncertainty about the correct formula. Either implement the division with proper explanation, or remove the comment if the current implementation is correct. The presence of this comment indicates the flux calculation may need verification.

Suggested change
flux_down[i, j, 0] = slope_diff[i, j] * grad_h_down[i, j, 0]# / grad_h[i, j]
flux_down[i, j, 1] = slope_diff[i, j] * grad_h_down[i, j, 1]# / grad_h[i, j]
# Normalize the direction vector to ensure flux is in the direction of the gradient with correct magnitude
flux_down[i, j, 0] = slope_diff[i, j] * grad_h_down[i, j, 0] / grad_h[i, j]
flux_down[i, j, 1] = slope_diff[i, j] * grad_h_down[i, j, 1] / grad_h[i, j]

Copilot uses AI. Check for mistakes.
Comment on lines 236 to 238
# from west neighbor (positive f_x of west cell) with periodic wrap
inc_west[:, 1:] = np.maximum(f_x[:, :-1], 0.0)
inc_west[:, 0] = np.maximum(f_x[:, -1], 0.0)
Copy link

Copilot AI Oct 25, 2025

Choose a reason for hiding this comment

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

The implementation applies periodic boundary conditions in the X direction (lines 237-238, 242-243) and Y direction (lines 247-248, 252-253), but the gradient calculations use fixed zero-gradient boundaries (lines 155-156, 169-170). This inconsistency between gradient and flux boundary treatments will cause mass conservation issues at domain boundaries.

Copilot uses AI. Check for mistakes.
Comment on lines 257 to 265
# # check mass balance in the presence of non-erodible layer
if np.any(zb + E * (q_in - q_out) < zne):
# update bed level with non-erodible layer limit
# this will effectively shut down further avalanching from the cells concerned
# because zb will equal zne there in the next iteration
zb += (zne - zb)
else:
# update bed level without non-erodible layer
zb += E * (q_in - q_out)
Copy link

Copilot AI Oct 25, 2025

Choose a reason for hiding this comment

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

When the non-erodible layer constraint is violated, all cells are updated to zb = zne (line 262) rather than only the cells that violate the constraint. This incorrectly affects cells where zb > zne. The update should be applied selectively: zb = np.maximum(zb + E * (q_in - q_out), zne).

Suggested change
# # check mass balance in the presence of non-erodible layer
if np.any(zb + E * (q_in - q_out) < zne):
# update bed level with non-erodible layer limit
# this will effectively shut down further avalanching from the cells concerned
# because zb will equal zne there in the next iteration
zb += (zne - zb)
else:
# update bed level without non-erodible layer
zb += E * (q_in - q_out)
# update bed level, ensuring it does not fall below the non-erodible layer
zb = np.maximum(zb + E * (q_in - q_out), zne)

Copilot uses AI. Check for mistakes.
Sierd and others added 2 commits October 25, 2025 12:50
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@Sierd Sierd requested a review from bartvanwesten October 25, 2025 10:57
@Sierd Sierd closed this Nov 6, 2025
@Sierd Sierd deleted the avalanching-numba-patch branch November 6, 2025 09:34
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