Note

This page was generated from a jupyter notebook.

Using SedimentPulserEachParcel to add sediment parcels to a channel network

This tutorial illustrates how to use SedimentPulserEachParcel with a network model grid and the NetworkSedimentTransporter.

  • SedimentPulserEachParcel overview: The user specifies the link and distance on link that parcels are placed within a channel network in a Pandas DataFrame.

In this example we will:

  1. Set up a network model grid with an initial set of parcels,

  2. Add pulses of sediment to the grid using SedimentPulserEachParcel, and

  3. Run NetworkSedimentTransporter between pulses

1. Setup the work space

[1]:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

from landlab.components import FlowDirectorSteepest, NetworkSedimentTransporter
from landlab.components.network_sediment_transporter.bed_parcel_initializers import (
    BedParcelInitializerArea,
)
from landlab.components.network_sediment_transporter.sediment_pulser_each_parcel import (
    SedimentPulserEachParcel,
)
from landlab.grid.network import NetworkModelGrid
from landlab.plot import graph, plot_network_and_parcels

2. Define the network model grid topology

[2]:
x_of_node = (0, 0, 100, -50, -100, 50, -150, -100)
y_of_node = (0, 100, 200, 200, 300, 400, 400, 125)
nodes_at_link = ((1, 0), (1, 2), (7, 1), (3, 1), (4, 3), (5, 4), (6, 4))
nmg = NetworkModelGrid((y_of_node, x_of_node), nodes_at_link)

to help visualize where the pulses will be sent, plot the network with link and node id numbers

[3]:
fig, axs = plt.subplots(1, 1, figsize=(4, 6))
graph.plot_links(nmg, with_id=True)
graph.plot_nodes(nmg, with_id=True)
../../_images/tutorials_network_sediment_transporter_sediment_pulser_each_parcel_6_0.png

4. Create an initial set of parcels on the grid.

Note, we start with a small number of initial parcels so that parcels from later pulses of material are visible in plots of the parcels and network

[5]:
initialize_parcels = BedParcelInitializerArea(
    nmg,
    drainage_area_coefficient=0.1,
    drainage_area_exponent=0.2,
    median_number_of_starting_parcels=2,
)
parcels = initialize_parcels()
/Users/runner/work/landlab/landlab/.nox/test-notebooks-3-12/lib/python3.12/site-packages/landlab/components/network_sediment_transporter/bed_parcel_initializers.py:82: UserWarning: at least one link has only [3 1 3 2 2 1 3] parcels.
  variables, items = _parcel_characteristics(

View the initial parcels on the network model grid, shaded by grain diameter

[6]:
fig = plot_network_and_parcels(
    nmg,
    parcels,
    parcel_time_index=0,  # index of time, not the time value
    parcel_color_attribute="D",
    parcel_size=10,
    parcel_alpha=1.0,
    figsize=(3, 6),
)
../../_images/tutorials_network_sediment_transporter_sediment_pulser_each_parcel_12_0.png

Viewing the element id of the parcels in the network shows that ParcelInitializer added 15 parcels to the network

[7]:
parcels.dataset["element_id"]
[7]:
<xarray.DataArray 'element_id' (item_id: 15, time: 1)> Size: 120B
array([[0],
       [0],
       [0],
       [1],
       [2],
       [2],
       [2],
       [3],
       [3],
       [4],
       [4],
       [5],
       [6],
       [6],
       [6]])
Coordinates:
  * time     (time) float64 8B 0.0
  * item_id  (item_id) int64 120B 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
Attributes:
    dtype:    <class 'int'>

6. Instantiate SedimentPulserEachParcel

SedimentPulserEachParcel is instantiated with a network model grid. Optionally, default parcel attributes and a parcel DataRecord can be defined. If a parcel DataRecord is not provided, SedimentPulserEachParcel will create a new parcel DataRecord.

[11]:
make_pulse = SedimentPulserEachParcel(
    nmg, parcels=parcels, parcel_volume=1
)  # set the default max parcel_volume as 1 m^3

7. create the PulseDF (Pulse DataFrame).

Each row of the PulseDF contains information on the deposition location and volume of a single pulse of sediment. The pulse is divided into ‘n’ number of parcels, where ‘n’ equals numpy.ceil(pulse volume / max parcel volume) For details on the format of the PulseDF, see the docstring for function SedimentPulserEachParcel._sediment_pulse_dataframe

Here we send a pulse to specific locations on links 1, 3, 5 and 2(see first figure for link id’s)> Note that any parcel attributes not specified use default values. Default values can be set when SedimentPulserAtLinks is instantiated.

[12]:
time = nst.time
# volume of each pulse
PulseDF = pd.DataFrame(
    {
        "pulse_volume": [50, 5, 10, 15],
        # pulses enter channel network at these links
        "link_#": [1, 3, 5, 2],
        # the normalized distance on the link (distance from link inlet / link length)
        "normalized_downstream_distance": [0.8, 0.7, 0.5, 0.2],
    }
)
[13]:
parcels = make_pulse(time, PulseDF)

view the location of the new parcels from the pulse.

Note that all parcels from a pulse are placed at the same point in the network and appear as 4 points on the plot

[14]:
fig = plot_network_and_parcels(
    nmg,
    parcels,
    parcel_time_index=1,  # index of time, not the time value
    parcel_color_attribute="D",
    parcel_size=10,
    parcel_alpha=1.0,
    figsize=(3, 6),
)
../../_images/tutorials_network_sediment_transporter_sediment_pulser_each_parcel_27_0.png

Viewing the element id of the parcels in the network shows that we actually added roughly 80 new parcels

[15]:
parcels.dataset["element_id"]
[15]:
<xarray.DataArray 'element_id' (item_id: 95, time: 2)> Size: 2kB
array([[ 0., -2.],
       [ 0.,  0.],
       [ 0.,  0.],
       [ 1.,  1.],
       [ 2., -2.],
       [ 2.,  2.],
       [ 2.,  2.],
       [ 3.,  3.],
       [ 3.,  3.],
       [ 4.,  4.],
       [ 4.,  4.],
       [ 5.,  5.],
       [ 6.,  6.],
       [ 6.,  6.],
       [ 6.,  6.],
       [nan,  1.],
       [nan,  1.],
       [nan,  1.],
       [nan,  1.],
       [nan,  1.],
...
       [nan,  5.],
       [nan,  5.],
       [nan,  5.],
       [nan,  5.],
       [nan,  5.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.],
       [nan,  2.]])
Coordinates:
  * time     (time) float64 16B 0.0 8.64e+04
  * item_id  (item_id) int64 760B 0 1 2 3 4 5 6 7 8 ... 87 88 89 90 91 92 93 94

now apply another 24 hr flow event

[16]:
nst.run_one_step(dt=3600 * 24)

View parcel locations after the flow event

[17]:
fig = plot_network_and_parcels(
    nmg,
    parcels,
    parcel_time_index=2,  # index of time, not the time value
    parcel_color_attribute="D",
    parcel_size=10,
    parcel_alpha=1.0,
    figsize=(3, 6),
)
../../_images/tutorials_network_sediment_transporter_sediment_pulser_each_parcel_33_0.png

Notice that after the flow event, the parcels at each pulse location spread out.

8. Send a second pulseDF

This pulseDF includes two pulses:

  1. A 30 m^3 landslide in thin-bedded siltstone near the channel head (inlet) of link 3

  2. A 50 m^3 bedrock landslide in fractured, massive sandstone beds near the outlet of link 6

[18]:
time = nst.time
PulseDF = pd.DataFrame(
    {
        "pulse_volume": [30, 50],  # pulse volume
        "link_#": [3, 6],  # link id
        "normalized_downstream_distance": [0.1, 0.9],  # distance on link
        "D50": [0.02, 0.5],  # median grain size
        "abrasion_rate": [0.1, 0.01],  # abrasion rate
        "parcel_volume": [0.25, 2],
    }
)  # parcel volume
[19]:
parcels = make_pulse(time, PulseDF)

view the new parcels

[20]:
fig = plot_network_and_parcels(
    nmg,
    parcels,
    parcel_time_index=2,  # index of time, not the time value
    parcel_color_attribute="D",
    parcel_size=10,
    parcel_alpha=1.0,
    figsize=(3, 6),
)
../../_images/tutorials_network_sediment_transporter_sediment_pulser_each_parcel_39_0.png

apply another day long flow event

[21]:
nst.run_one_step(dt=3600 * 24)
[22]:
fig = plot_network_and_parcels(
    nmg,
    parcels,
    parcel_time_index=3,  # index of time, not the time value
    parcel_color_attribute="D",
    parcel_size=10,
    parcel_alpha=1.0,
    figsize=(3, 6),
)
../../_images/tutorials_network_sediment_transporter_sediment_pulser_each_parcel_42_0.png

Generated by nbsphinx from a Jupyter notebook.