Introduction
Introduction Statistics Contact Development Disclaimer Help
ttransport sediment for more than one cell - granular-channel-hydro - subglacia…
git clone git://src.adamsgaard.dk/granular-channel-hydro
Log
Files
Refs
README
LICENSE
---
commit 400da52ca6dea9a381f902ba653ca1c267ac286f
parent 26bc00c665916c00d8fc195170f6df2062d77332
Author: Anders Damsgaard Christensen <[email protected]>
Date: Thu, 2 Feb 2017 16:22:16 -0800
ttransport sediment for more than one cell
Diffstat:
A 1d-channel-flux.py | 292 +++++++++++++++++++++++++++++…
M 1d-channel.py | 153 +++++++++++++++++------------…
2 files changed, 377 insertions(+), 68 deletions(-)
---
diff --git a/1d-channel-flux.py b/1d-channel-flux.py
t@@ -0,0 +1,292 @@
+#!/usr/bin/env python
+
+# # ABOUT THIS FILE
+# The following script uses basic Python and Numpy functionality to solve the
+# coupled systems of equations describing subglacial channel development in
+# soft beds as presented in `Damsgaard et al. "Sediment plasticity controls
+# channelization of subglacial meltwater in soft beds"`, submitted to Journal
+# of Glaciology.
+#
+# High performance is not the goal for this implementation, which is instead
+# intended as a heavily annotated example on the solution procedure without
+# relying on solver libraries, suitable for low-level languages like C, Fortran
+# or CUDA.
+#
+# License: Gnu Public License v3
+# Author: Anders Damsgaard, [email protected], https://adamsgaard.dk
+
+import numpy
+import matplotlib.pyplot as plt
+import sys
+
+
+# # Model parameters
+Ns = 25 # Number of nodes [-]
+Ls = 100e3 # Model length [m]
+t_end = 24.*60.*60.*120. # Total simulation time [s]
+tol_Q = 1e-3 # Tolerance criteria for the normalized max. residual for Q
+tol_P_c = 1e-3 # Tolerance criteria for the normalized max residual for P_c
+max_iter = 1e2*Ns # Maximum number of solver iterations before failure
+output_convergence = False # Display convergence statistics during run
+safety = 0.1 # Safety factor ]0;1] for adaptive timestepping
+
+# Physical parameters
+rho_w = 1000. # Water density [kg/m^3]
+rho_i = 910. # Ice density [kg/m^3]
+rho_s = 2600. # Sediment density [kg/m^3]
+g = 9.8 # Gravitational acceleration [m/s^2]
+theta = 30. # Angle of internal friction in sediment [deg]
+
+# Water source term [m/s]
+# m_dot = 7.93e-11
+m_dot = 4.5e-8
+# m_dot = 5.79e-5
+
+# Hewitt 2011 channel flux parameters
+manning = 0.1 # Manning roughness coefficient [m^{-1/3} s]
+F = rho_w*g*manning*(2.*(numpy.pi + 2.)**2./numpy.pi)**(2./3.)
+
+# Channel growth-limit parameters
+c_1 = -0.118 # [m/kPa]
+c_2 = 4.60 # [m]
+
+# Minimum channel size [m^2], must be bigger than 0
+# S_min = 1e-1
+S_min = 1.5e-2
+
+
+# # Initialize model arrays
+# Node positions, terminus at Ls
+s = numpy.linspace(0., Ls, Ns)
+ds = s[1:] - s[:-1]
+
+# Ice thickness and bed topography
+H = 6.*(numpy.sqrt(Ls - s + 5e3) - numpy.sqrt(5e3)) + 1.0 # max: 1.5 km
+# H = 1.*(numpy.sqrt(Ls - s + 5e3) - numpy.sqrt(5e3)) + 1.0 # max: 255 m
+# H = 0.6*(numpy.sqrt(Ls - s + 5e3) - numpy.sqrt(5e3)) + 1.0
+b = numpy.zeros_like(H)
+
+N = H*0.1*rho_i*g # Initial effective stress [Pa]
+p_w = rho_i*g*H - N # Initial guess of water pressure [Pa]
+hydro_pot = rho_w*g*b + p_w # Initial guess of hydraulic potential [Pa]
+
+# Initialize arrays for channel segments between nodes
+S = numpy.ones(len(s) - 1)*S_min # Cross-sect. area of channel segments [m^2]
+S_max = numpy.zeros_like(S) # Max. channel size [m^2]
+dSdt = numpy.zeros_like(S) # Transient in channel cross-sect. area [m^2/s]
+W = S/numpy.tan(numpy.deg2rad(theta)) # Assuming no channel floor wedge
+Q = numpy.zeros_like(S) # Water flux in channel segments [m^3/s]
+Q_s = numpy.zeros_like(S) # Sediment flux in channel segments [m^3/s]
+dQ_s_ds = numpy.empty_like(S) # Transient in channel cross-sect. area [m^2/s]
+N_c = numpy.zeros_like(S) # Effective pressure in channel segments [Pa]
+P_c = numpy.zeros_like(S) # Water pressure in channel segments [Pa]
+res = numpy.zeros_like(S) # Solution residual during solver iterations
+
+
+# # Helper functions
+def gradient(arr, arr_x):
+ # Central difference gradient of an array ``arr`` with node positions at
+ # ``arr_x``.
+ return (arr[:-1] - arr[1:])/(arr_x[:-1] - arr_x[1:])
+
+def avg_midpoint(arr):
+ # Averaged value of neighboring array elements
+ return (arr[:-1] + arr[1:])/2.
+
+def channel_water_flux(S, hydro_pot_grad):
+ # Hewitt 2011
+ return numpy.sqrt(1./F*S**(8./3.)*-hydro_pot_grad)
+
+def update_channel_size_with_limit(S, dSdt, dt, N):
+ # Damsgaard et al, in prep
+ S_max = ((c_1*N.clip(min=0.)/1000. + c_2)*\
+ numpy.tan(numpy.deg2rad(theta))).clip(min=S_min)
+ S = numpy.minimum(S + dSdt*dt, S_max).clip(min=S_min)
+ W = S/numpy.tan(numpy.deg2rad(theta)) # Assume no channel floor wedge
+ return S, W, S_max
+
+def flux_solver(m_dot, ds):
+ # Iteratively find new fluxes
+ it = 0
+ max_res = 1e9 # arbitrary large value
+
+ # Iteratively find solution, do not settle for less iterations than the
+ # number of nodes
+ while max_res > tol_Q or it < Ns:
+
+ Q_old = Q.copy()
+ # dQ/ds = m_dot -> Q_out = m*delta(s) + Q_in
+ # Upwind information propagation (upwind)
+ Q[0] = 1e-2 # Ng 2000
+ Q[1:] = m_dot*ds[1:] + Q[:-1]
+ max_res = numpy.max(numpy.abs((Q - Q_old)/(Q + 1e-16)))
+
+ if output_convergence:
+ print('it = {}: max_res = {}'.format(it, max_res))
+
+ #import ipdb; ipdb.set_trace()
+ if it >= max_iter:
+ raise Exception('t = {}, step = {}:'.format(time, step) +
+ 'Iterative solution not found for Q')
+ it += 1
+
+ return Q
+
+def sediment_flux(Q):
+ #return Q**(3./2.)
+ return Q/2.
+
+def sediment_flux_divergence(Q_s, ds):
+ # Damsgaard et al, in prep
+ return (Q_s[1:] - Q_s[:-1])/ds[1:]
+
+def pressure_solver(psi, F, Q, S):
+ # Iteratively find new water pressures
+ # dP_c/ds = psi - FQ^2/S^{8/3}
+
+ it = 0
+ max_res = 1e9 # arbitrary large value
+ while max_res > tol_P_c or it < Ns*40:
+
+ P_c_old = P_c.copy()
+
+ # Upwind finite differences
+ P_c[:-1] = -psi[:-1]*ds[:-1] \
+ + F*Q[:-1]**2./(S[:-1]**(8./3.))*ds[:-1] \
+ + P_c[1:] # Upstream
+
+ # Dirichlet BC (fixed pressure) at terminus
+ P_c[-1] = 0.
+
+ # von Neumann BC (no gradient = no flux) at s=0
+ P_c[0] = P_c[1]
+
+ max_res = numpy.max(numpy.abs((P_c - P_c_old)/(P_c + 1e-16)))
+
+ if output_convergence:
+ print('it = {}: max_res = {}'.format(it, max_res))
+
+ if it >= max_iter:
+ raise Exception('t = {}, step = {}:'.format(time, step) +
+ 'Iterative solution not found for P_c')
+ it += 1
+
+ return P_c
+
+def plot_state(step, time):
+ # Plot parameters along profile
+ fig = plt.gcf()
+ fig.set_size_inches(3.3, 3.3)
+
+ ax_Pa = plt.subplot(2, 1, 1) # axis with Pascals as y-axis unit
+ ax_Pa.plot(s_c/1000., P_c/1000., '--r', label='$P_c$')
+
+ ax_m3s = ax_Pa.twinx() # axis with m3/s as y-axis unit
+ ax_m3s.plot(s_c/1000., Q, '-b', label='$Q$')
+ ax_m3s.plot(s_c/1000., Q_s, ':b', label='$Q_s$')
+
+ plt.title('Day: {:.3}'.format(time/(60.*60.*24.)))
+ ax_Pa.legend(loc=2)
+ ax_m3s.legend(loc=1)
+ ax_Pa.set_ylabel('[kPa]')
+ ax_m3s.set_ylabel('[m$^3$/s]')
+
+ ax_m2 = plt.subplot(2, 1, 2, sharex=ax_Pa)
+ ax_m2.plot(s_c/1000., S, '-k', label='$S$')
+ ax_m2.plot(s_c/1000., S_max, '--k', label='$S_{max}$')
+ #ax_m.semilogy(s_c/1000., S, '-k', label='$S$')
+ #ax_m.semilogy(s_c/1000., S_max, '--k', label='$S_{max}$')
+
+ ax_m2s = ax_m2.twinx()
+ ax_m2s.plot(s_c/1000., dSdt, ':b', label='$dS/dt$')
+
+ ax_m2.legend(loc=2)
+ ax_m2s.legend(loc=1)
+ ax_m2.set_xlabel('$s$ [km]')
+ ax_m2.set_ylabel('[m$^2$]')
+ ax_m2s.set_ylabel('[m$^2$/s]')
+
+ plt.setp(ax_Pa.get_xticklabels(), visible=False)
+ plt.tight_layout()
+ if step == -1:
+ plt.savefig('chan-0.init.pdf')
+ else:
+ plt.savefig('chan-' + str(step) + '.pdf')
+ plt.clf()
+
+def find_new_timestep(ds, Q, S):
+ # Determine the timestep using the Courant-Friedrichs-Lewy condition
+ dt = safety*numpy.minimum(60.*60.*24., numpy.min(numpy.abs(ds/(Q*S))))
+
+ if dt < 1.0:
+ raise Exception('Error: Time step less than 1 second at step '
+ + '{}, time '.format(step)
+ + '{:.3} s/{:.3} d'.format(time, time/(60.*60.*24.)))
+
+ return dt
+
+def print_status_to_stdout(time, dt):
+ sys.stdout.write('\rt = {:.2} s or {:.4} d, dt = {:.2} s '\
+ .format(time, time/(60.*60.*24.), dt))
+ sys.stdout.flush()
+
+s_c = avg_midpoint(s) # Channel section midpoint coordinates [m]
+
+# Find gradient in hydraulic potential between the nodes
+hydro_pot_grad = gradient(hydro_pot, s)
+
+# Find field values at the middle of channel segments
+N_c = avg_midpoint(N)
+H_c = avg_midpoint(N)
+
+# Find fluxes in channel segments [m^3/s]
+Q = channel_water_flux(S, hydro_pot_grad)
+
+# Water-pressure gradient from geometry [Pa/m]
+psi = -rho_i*g*gradient(H, s) - (rho_w - rho_i)*g*gradient(b, s)
+
+# Prepare figure object for plotting during the simulation
+fig = plt.figure('channel')
+plot_state(-1, 0.0)
+
+
+# # Time loop
+time = 0.; step = 0
+while time <= t_end:
+
+ #print('@ @ @ step ' + str(step))
+
+ dt = find_new_timestep(ds, Q, S)
+
+ print_status_to_stdout(time, dt)
+
+ # Find the sediment flux
+ Q_s = sediment_flux(Q)
+
+ # Find sediment flux divergence which determines channel growth, no growth
+ # in first segment
+ dSdt[1:] = sediment_flux_divergence(Q_s, ds)
+
+ # Update channel cross-sectional area and width according to growth rate
+ # and size limit for each channel segment
+ S, W, S_max = update_channel_size_with_limit(S, dSdt, dt, N_c)
+
+ # Find new water fluxes consistent with mass conservation and local
+ # meltwater production (m_dot)
+ Q = flux_solver(m_dot, ds)
+
+ # Find new water pressures consistent with the flow law
+ P_c = pressure_solver(psi, F, Q, S)
+
+ # Find new effective pressure in channel segments
+ N_c = rho_i*g*H_c - P_c
+
+ plot_state(step, time)
+
+ #import ipdb; ipdb.set_trace()
+ #if step > 0:
+ #break
+
+ # Update time
+ time += dt
+ step += 1
diff --git a/1d-channel.py b/1d-channel.py
t@@ -1,6 +1,6 @@
#!/usr/bin/env python
-## ABOUT THIS FILE
+# # ABOUT THIS FILE
# The following script uses basic Python and Numpy functionality to solve the
# coupled systems of equations describing subglacial channel development in
# soft beds as presented in `Damsgaard et al. "Sediment plasticity controls
t@@ -20,38 +20,37 @@ import matplotlib.pyplot as plt
import sys
-## Model parameters
-Ns = 25 # Number of nodes [-]
-Ls = 100e3 # Model length [m]
-t_end = 24.*60.*60.*2 # Total simulation time [s]
-tol_Q = 1e-3 # Tolerance criteria for the normalized max. residual for Q
-tol_P_c = 1e-3 # Tolerance criteria for the normalized max. residual for P_c
-max_iter = 1e2*Ns # Maximum number of solver iterations before failure
+# # Model parameters
+Ns = 25 # Number of nodes [-]
+Ls = 100e3 # Model length [m]
+t_end = 24.*60.*60.*2 # Total simulation time [s]
+tol_Q = 1e-3 # Tolerance criteria for the normalized max. residual for Q
+tol_P_c = 1e-3 # Tolerance criteria for the normalized max residual for P_c
+max_iter = 1e2*Ns # Maximum number of solver iterations before failure
output_convergence = False # Display convergence statistics during run
safety = 0.1 # Safety factor ]0;1] for adaptive timestepping
# Physical parameters
-rho_w = 1000. # Water density [kg/m^3]
-rho_i = 910. # Ice density [kg/m^3]
-rho_s = 2600. # Sediment density [kg/m^3]
-g = 9.8 # Gravitational acceleration [m/s^2]
-theta = 30. # Angle of internal friction in sediment [deg]
+rho_w = 1000. # Water density [kg/m^3]
+rho_i = 910. # Ice density [kg/m^3]
+rho_s = 2600. # Sediment density [kg/m^3]
+g = 9.8 # Gravitational acceleration [m/s^2]
+theta = 30. # Angle of internal friction in sediment [deg]
# Water source term [m/s]
-#m_dot = 7.93e-11
+# m_dot = 7.93e-11
m_dot = 4.5e-7
-#m_dot = 5.79e-5
+# m_dot = 5.79e-5
# Walder and Fowler 1994 sediment transport parameters
K_e = 0.1 # Erosion constant [-], disabled when 0.0
-#K_d = 6.0 # Deposition constant [-], disabled when 0.0
-K_d = 1e-1 # Deposition constant [-], disabled when 0.0
+K_d = 6.0 # Deposition constant [-], disabled when 0.0
alpha = 2e5 # Geometric correction factor (Carter et al 2017)
-#D50 = 1e-3 # Median grain size [m]
-#tau_c = 0.5*g*(rho_s - rho_i)*D50 # Critical shear stress for transport
+# D50 = 1e-3 # Median grain size [m]
+# tau_c = 0.5*g*(rho_s - rho_i)*D50 # Critical shear stress for transport
d15 = 1e-3 # Characteristic grain size [m]
tau_c = 0.025*d15*g*(rho_s - rho_i) # Critical shear stress (Carter 2017)
-#tau_c = 0.
+# tau_c = 0.
mu_w = 1.787e-3 # Water viscosity [Pa*s]
froude = 0.1 # Friction factor [-]
v_s = d15**2.*g*2.*(rho_s - rho_i)/(9.*mu_w) # Settling velocity (Carter 2017)
t@@ -61,22 +60,22 @@ manning = 0.1 # Manning roughness coefficient [m^{-1/3} s]
F = rho_w*g*manning*(2.*(numpy.pi + 2)**2./numpy.pi)**(2./3.)
# Channel growth-limit parameters
-c_1 = -0.118 # [m/kPa]
-c_2 = 4.60 # [m]
+c_1 = -0.118 # [m/kPa]
+c_2 = 4.60 # [m]
# Minimum channel size [m^2], must be bigger than 0
S_min = 1e-1
-## Initialize model arrays
+# # Initialize model arrays
# Node positions, terminus at Ls
s = numpy.linspace(0., Ls, Ns)
ds = s[1:] - s[:-1]
# Ice thickness and bed topography
H = 6.*(numpy.sqrt(Ls - s + 5e3) - numpy.sqrt(5e3)) + 1.0 # max: 1.5 km
-#H = 1.*(numpy.sqrt(Ls - s + 5e3) - numpy.sqrt(5e3)) + 1.0 # max: 255 m
-#H = 0.6*(numpy.sqrt(Ls - s + 5e3) - numpy.sqrt(5e3)) + 1.0
+# H = 1.*(numpy.sqrt(Ls - s + 5e3) - numpy.sqrt(5e3)) + 1.0 # max: 255 m
+# H = 0.6*(numpy.sqrt(Ls - s + 5e3) - numpy.sqrt(5e3)) + 1.0
b = numpy.zeros_like(H)
N = H*0.1*rho_i*g # Initial effective stress [Pa]
t@@ -84,79 +83,88 @@ p_w = rho_i*g*H - N # Initial guess of water pres…
hydro_pot = rho_w*g*b + p_w # Initial guess of hydraulic potential [Pa]
# Initialize arrays for channel segments between nodes
-S = numpy.ones(len(s) - 1)*S_min # Cross-sectional area of channel segments[m^…
-S_max = numpy.zeros_like(S) # Max. channel size [m^2]
-dSdt = numpy.empty_like(S) # Transient in channel cross-sectional area [m^2/s]
+S = numpy.ones(len(s) - 1)*S_min # Cross-sect. area of channel segments[m^2]
+S_max = numpy.zeros_like(S) # Max. channel size [m^2]
+dSdt = numpy.empty_like(S) # Transient in channel cross-sect. area [m^2/s]
W = S/numpy.tan(numpy.deg2rad(theta)) # Assuming no channel floor wedge
-Q = numpy.zeros_like(S) # Water flux in channel segments [m^3/s]
-Q_s = numpy.zeros_like(S) # Sediment flux in channel segments [m^3/s]
-N_c = numpy.zeros_like(S) # Effective pressure in channel segments [Pa]
-P_c = numpy.zeros_like(S) # Water pressure in channel segments [Pa]
-e_dot = numpy.zeros_like(S) # Sediment erosion rate in channel segments [m/s]
-d_dot = numpy.zeros_like(S) # Sediment deposition rate in chan. segments [m/s]
-c_bar = numpy.zeros_like(S) # Vertically integrated sediment concentration [-]
-tau = numpy.zeros_like(S) # Avg. shear stress from current [Pa]
-porosity = numpy.ones_like(S)*0.3 # Sediment porosity [-]
+Q = numpy.zeros_like(S) # Water flux in channel segments [m^3/s]
+Q_s = numpy.zeros_like(S) # Sediment flux in channel segments [m^3/s]
+N_c = numpy.zeros_like(S) # Effective pressure in channel segments [Pa]
+P_c = numpy.zeros_like(S) # Water pressure in channel segments [Pa]
+e_dot = numpy.zeros_like(S) # Sediment erosion rate in channel segments [m/s]
+d_dot = numpy.zeros_like(S) # Sediment deposition rate in chan. segments [m/s]
+c_bar = numpy.zeros_like(S) # Vertically integrated sediment concentration [-]
+tau = numpy.zeros_like(S) # Avg. shear stress from current [Pa]
+porosity = numpy.ones_like(S)*0.3 # Sediment porosity [-]
res = numpy.zeros_like(S) # Solution residual during solver iterations
-## Helper functions
+# # Helper functions
def gradient(arr, arr_x):
# Central difference gradient of an array ``arr`` with node positions at
# ``arr_x``.
return (arr[:-1] - arr[1:])/(arr_x[:-1] - arr_x[1:])
+
def avg_midpoint(arr):
# Averaged value of neighboring array elements
return (arr[:-1] + arr[1:])/2.
+
def channel_water_flux(S, hydro_pot_grad):
# Hewitt 2011
return numpy.sqrt(1./F*S**(8./3.)*-hydro_pot_grad)
+
def channel_shear_stress(Q, S):
# Weertman 1972, Walder and Fowler 1994
u_bar = Q/S
return 1./8.*froude*rho_w*u_bar**2.
+
def channel_erosion_rate(tau):
# Parker 1979, Walder and Fowler 1994
- #return K_e*v_s*(tau - tau_c).clip(min=0.)/(g*(rho_s - rho_w)*d15)
+ # return K_e*v_s*(tau - tau_c).clip(min=0.)/(g*(rho_s - rho_w)*d15)
# Carter et al 2017
return K_e*v_s/alpha*(tau - tau_c).clip(min=0.)/(g*(rho_s - rho_w)*d15)
+
def channel_deposition_rate_kernel(tau, c_bar, ix):
# Parker 1979, Walder and Fowler 1994
- #result = K_d*v_s*c_bar[ix]*(g*(rho_s - rho_w)*d15/tau[ix])**0.5
+ # result = K_d*v_s*c_bar[ix]*(g*(rho_s - rho_w)*d15/tau[ix])**0.5
# Carter et al. 2017
result = K_d*v_s/alpha*c_bar[ix]*(g*(rho_s - rho_w)*d15/tau[ix])**0.5
+ '''
print('tau[{}] = {}'.format(ix, tau[ix]))
print('c_bar[{}] = {}'.format(ix, c_bar[ix]))
print('e_dot[{}] = {}'.format(ix, e_dot[ix]))
print('d_dot[{}] = {}'.format(ix, result))
print('')
+ '''
return result
+
def channel_deposition_rate_kernel_ng(c_bar, ix):
# Ng 2000
h = W[ix]/2.*numpy.tan(numpy.deg2rad(theta))
- epsilon = numpy.sqrt((psi[ix] - (P_c[ix] - P_c[ix - 1])/ds[ix])\
- /(rho_w*froude))*h**(3./2.)
+ epsilon = numpy.sqrt((psi[ix] - (P_c[ix] - P_c[ix - 1])/ds[ix])
+ / (rho_w*froude))*h**(3./2.)
return v_s/epsilon*c_bar[ix]
+
def channel_deposition_rate(tau, c_bar, d_dot, Ns):
# Parker 1979, Walder and Fowler 1994
# Find deposition rate from upstream to downstream, margin at is=0
-
+ '''
print("\n## Before loop:")
print(c_bar)
print(d_dot)
print('')
-
+ '''
# No sediment deposition at upstream end
c_bar[0] = 0.
t@@ -164,36 +172,39 @@ def channel_deposition_rate(tau, c_bar, d_dot, Ns):
for ix in numpy.arange(1, Ns - 1):
# Net erosion in upstream cell
- #c_bar[ix] = numpy.maximum((e_dot[ix-1] - d_dot[ix-1])*dt*ds[ix-1], 0.)
- c_bar[ix] = numpy.maximum(
- W[ix - 1]*ds[ix - 1]*rho_s/rho_w*
- (e_dot[ix - 1] - d_dot[ix - 1])/Q[ix - 1]
- , 0.)
-
- #d_dot[ix] = channel_deposition_rate_kernel(tau, c_bar, ix)
- d_dot[ix] = channel_deposition_rate_kernel_ng(c_bar, ix)
+ # c_bar[ix] = numpy.maximum((e_dot[ix-1]-d_dot[ix-1])*dt*ds[ix-1], 0.)
+ c_bar[ix] = c_bar[ix - 1] + \
+ numpy.maximum(
+ W[ix - 1]*ds[ix - 1]*rho_s/rho_w *
+ (e_dot[ix - 1] - d_dot[ix - 1])/Q[ix - 1], 0.)
+ d_dot[ix] = channel_deposition_rate_kernel(tau, c_bar, ix)
+ # d_dot[ix] = channel_deposition_rate_kernel_ng(c_bar, ix)
+ '''
print("\n## After loop:")
print(c_bar)
print(d_dot)
print('')
-
+ '''
return d_dot, c_bar
+
def channel_growth_rate(e_dot, d_dot, porosity, W):
# Damsgaard et al, in prep
return (e_dot - d_dot)/porosity*W
+
def update_channel_size_with_limit(S, dSdt, dt, N):
# Damsgaard et al, in prep
- S_max = ((c_1*N/1000. + c_2)*\
+ S_max = ((c_1*N.clip(min=0.)/1000. + c_2) *
numpy.tan(numpy.deg2rad(theta))).clip(min=S_min)
S = numpy.minimum(S + dSdt*dt, S_max).clip(min=S_min)
W = S/numpy.tan(numpy.deg2rad(theta)) # Assume no channel floor wedge
return S, W, S_max
+
def flux_solver(m_dot, ds):
# Iteratively find new fluxes
it = 0
t@@ -213,7 +224,7 @@ def flux_solver(m_dot, ds):
if output_convergence:
print('it = {}: max_res = {}'.format(it, max_res))
- #import ipdb; ipdb.set_trace()
+ # import ipdb; ipdb.set_trace()
if it >= max_iter:
raise Exception('t = {}, step = {}:'.format(time, step) +
'Iterative solution not found for Q')
t@@ -221,11 +232,13 @@ def flux_solver(m_dot, ds):
return Q
+
def suspended_sediment_flux(c_bar, Q, S):
# Find the fluvial sediment flux through the system
# Q_s = c_bar * u * S, where u = Q/S
return c_bar*Q
+
def pressure_solver(psi, F, Q, S):
# Iteratively find new water pressures
# dP_c/ds = psi - FQ^2/S^{8/3}
t@@ -259,6 +272,7 @@ def pressure_solver(psi, F, Q, S):
return P_c
+
def plot_state(step, time):
# Plot parameters along profile
fig = plt.gcf()
t@@ -277,10 +291,10 @@ def plot_state(step, time):
ax_m3s.set_ylabel('[m$^3$/s]')
ax_m = plt.subplot(2, 1, 2, sharex=ax_Pa)
- #ax_m.plot(s_c/1000., S, '-k', label='$S$')
- #ax_m.plot(s_c/1000., S_max, '--k', label='$S_{max}$')
- ax_m.semilogy(s_c/1000., S, '-k', label='$S$')
- ax_m.semilogy(s_c/1000., S_max, '--k', label='$S_{max}$')
+ ax_m.plot(s_c/1000., S, '-k', label='$S$')
+ ax_m.plot(s_c/1000., S_max, '--k', label='$S_{max}$')
+ # ax_m.semilogy(s_c/1000., S, '-k', label='$S$')
+ # ax_m.semilogy(s_c/1000., S_max, '--k', label='$S_{max}$')
ax_ms = ax_m.twinx()
ax_ms.plot(s_c/1000., e_dot, '--r', label='$\dot{e}$')
t@@ -300,6 +314,7 @@ def plot_state(step, time):
plt.savefig('chan-' + str(step) + '.pdf')
plt.clf()
+
def find_new_timestep(ds, Q, S):
# Determine the timestep using the Courant-Friedrichs-Lewy condition
dt = safety*numpy.minimum(60.*60.*24., numpy.min(numpy.abs(ds/(Q*S))))
t@@ -311,12 +326,13 @@ def find_new_timestep(ds, Q, S):
return dt
+
def print_status_to_stdout(time, dt):
- sys.stdout.write('\rt = {:.2} s or {:.4} d, dt = {:.2} s '\
+ sys.stdout.write('\rt = {:.2} s or {:.4} d, dt = {:.2} s '
.format(time, time/(60.*60.*24.), dt))
sys.stdout.flush()
-s_c = avg_midpoint(s) # Channel section midpoint coordinates [m]
+s_c = avg_midpoint(s) # Channel section midpoint coordinates [m]
# Find gradient in hydraulic potential between the nodes
hydro_pot_grad = gradient(hydro_pot, s)
t@@ -336,11 +352,12 @@ fig = plt.figure('channel')
plot_state(-1, 0.0)
-## Time loop
-time = 0.; step = 0
+# # Time loop
+time = 0.
+step = 0
while time <= t_end:
- #print('@ @ @ step ' + str(step))
+ # print('@ @ @ step ' + str(step))
dt = find_new_timestep(ds, Q, S)
t@@ -365,7 +382,7 @@ while time <= t_end:
Q = flux_solver(m_dot, ds)
# Find the corresponding sediment flux
- #Q_b = bedload_sediment_flux(
+ # Q_b = bedload_sediment_flux(
Q_s = suspended_sediment_flux(c_bar, Q, S)
# Find new water pressures consistent with the flow law
t@@ -376,9 +393,9 @@ while time <= t_end:
plot_state(step, time)
- #import ipdb; ipdb.set_trace()
- if step > 0:
- break
+ # import ipdb; ipdb.set_trace()
+ #if step > 0:
+ #break
# Update time
time += dt
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.