diff --git a/lessons/landlab/landlab/00_welcome.ipynb b/lessons/landlab/landlab/00_welcome.ipynb index 524fd2e..2b0ffdf 100644 --- a/lessons/landlab/landlab/00_welcome.ipynb +++ b/lessons/landlab/landlab/00_welcome.ipynb @@ -45,6 +45,8 @@ " * Calculations on a grid elements\n", " * Example: Fault scarp\n", "\n", + "* [Components](05-components.ipynb)\n", + " * Example: Fault scarp with LinearDiffuser\n", "\n", "## More examples\n", " \n", diff --git a/lessons/landlab/landlab/05-components.a.ipynb b/lessons/landlab/landlab/05-components.a.ipynb index 7fe0b7b..533210a 100644 --- a/lessons/landlab/landlab/05-components.a.ipynb +++ b/lessons/landlab/landlab/05-components.a.ipynb @@ -13,7 +13,7 @@ "source": [ "## Introduction to Landlab Components\n", "\n", - "A \"potluck\" is a meal in which each guest brings a dish to share. These contributed dishes usually come in one of a few categories: salads, drinks, main dishes, desserts. The meal comes together as a collection of components, each of which contributes to fulfilling one of these basic roles. The resulting meal provides guests with a great variety of choices. A guest can compose their own complete and unique meal by combining their own choices for components. And each guest, while contributing their own particular dish, get to share in the creations of their compatriots. There's a bit of standardization---the dishes are sized to fit on the tables, and their contents are accessible to the usual range of serving utensils---but with that standardization lies a great range of creativity.\n", + "A \"potluck\" is a common American tradition in which each guest brings a dish to share. These contributed dishes usually come in one of a few categories: salads, drinks, main dishes, desserts. The meal comes together as a collection of components, each of which contributes to fulfilling one of these basic roles. The resulting meal provides guests with a great variety of choices. A guest can compose their own complete and unique meal by combining their own choices for components. And each guest, while contributing their own particular dish, gets to share in the creations of their compatriots. There's a bit of standardization---the dishes are sized to fit on the tables, and their contents are accessible to the usual range of serving utensils---but with that standardization lies a great range of creativity.\n", "\n", "Component modeling is a bit like the potluck tradition: one can construct a complete simulation by assembling components to represent the different parts of the system to be modeled. In Landlab, a **component** is a semi-standardized Python *class* that represents a particular process or calculation. Components are not stand-alone programs, but rather are designed to be used within another Python program that creates an integrated model or workflow.\n", "\n", @@ -37,7 +37,13 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "source": [ "\n", "*Figure 3: cumulative infiltration water depth during a simulated five-minute heavy rainfall (from Landlab tutorial \"Green-Ampt infiltration and kinematic wave overland flow\")*\n", @@ -45,18 +51,16 @@ "The following code snippets illustrate how the components are imported...\n", "\n", "```python\n", - "from landlab.components import (\n", - " SoilInfiltrationGreenAmpt,\n", - " KinwaveImplicitOverlandFlow\n", - ")\n", + "from landlab.components import SoilInfiltrationGreenAmpt\n", + "from landlab.components import KinwaveImplicitOverlandFlow\n", "```\n", "\n", "...instantiated...\n", "\n", "```python\n", - "ga = SoilInfiltrationGreenAmpt(grid)\n", + "infiltration = SoilInfiltrationGreenAmpt(grid)\n", "\n", - "kw = KinwaveImplicitOverlandFlow(\n", + "overland_flow = KinwaveImplicitOverlandFlow(\n", " grid, runoff_rate=90.0, roughness=0.1, depth_exp=5.0 / 3.0\n", ")\n", "```\n", @@ -64,19 +68,25 @@ "...and run in a time loop:\n", "\n", "```python\n", - "for i in range(nsteps):\n", - " kw.run_one_step(dt)\n", - " ga.run_one_step(dt)\n", + "for _ in range(nsteps):\n", + " overland_flow.run_one_step(dt)\n", + " infiltration.run_one_step(dt)\n", "```" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "source": [ "### The Landlab component collection\n", "\n", - "The current (spring 2022) collection of components spans a variety of types of process and analysis. You can find a list [in the documentation](https://landlab.readthedocs.io/en/latest/reference/components/index.html).\n", + "The current collection of components spans a variety of types of process and analysis. You can find a list [in the documentation](https://landlab.csdms.io).\n", "\n", "To see a list, you can use the following python commands:" ] @@ -89,7 +99,8 @@ "source": [ "from landlab.components import COMPONENTS\n", "\n", - "[component.__name__ for component in COMPONENTS]" + "for component in COMPONENTS:\n", + " print(component.__name__)" ] }, { @@ -164,7 +175,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "If we want to see the complete documentation, we can also access this information using `?`, similar to how we accessed information from `RasterModelGrid` in part [Explore the Landlab grids](#Explore-the-Landlab-grids)." + "If we want to see the complete documentation, we can also access this information using `?`." ] }, { @@ -185,14 +196,14 @@ "source": [ "Note we haven't needed to instantiate the component in order to access any of this information. Instantiation occurs when we create a unique instance of the component with specific variables and parameter values (just like how we created instances of `RasterModelGrid` above with unique names, dimensions, and grid spacing.) Don't worry if this is confusing right now - it will make sense momentarily. \n", "\n", - "Since we know `LinearDiffuser` requires a topographic elevation field in order to be instantiated, we need to create that field. Recall that `topographic__elevation` is tied to grid nodes, so we actually need to create a grid instance, and add the `topographic__elevation` field onto the grid. This is just like the steps we took in part [Sediment diffusion](#Sediment-diffusion) of this tutorial." + "Since we know `LinearDiffuser` requires a topographic elevation field in order to be instantiated, we need to create that field. Recall that `topographic__elevation` is tied to grid nodes, so we actually need to create a grid instance, and add the `topographic__elevation` field onto the grid." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Create a new grid instance for the `LinearDiffuser` component to run on. Give your new grid a new name (perhaps `new_grid`?), but give it the same dimensions as `mg` (25 x 25, with 10m spacing)." + "Create a new grid instance for the `LinearDiffuser` component to run on. Give you grid 25 rows and colums with a node spacing of 10.0 m." ] }, { @@ -207,10 +218,18 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [ + "solution" + ] + }, "outputs": [], "source": [ - "grid = RasterModelGrid((25, 25), 10)" + "grid = RasterModelGrid((25, 25), xy_spacing=10)" ] }, { @@ -221,17 +240,39 @@ "\n", "$$\\frac{\\partial z}{\\partial t} = D \\nabla^2 z$$\n", "\n", - "As before, we need some topographic variation in order to drive diffusion. We'll still need to add our `topographic__elevation` field manually, and we'll need to create a \"fault\" on the grid by elevating half of the nodes. Let's do this now, following the format we used in [Sediment diffusion](#Sediment-diffusion)." + "As before, we need some topographic variation in order to drive diffusion. We'll still need to add our `topographic__elevation` field manually, and we'll need to create a \"fault\" on the grid by elevating half of the nodes." ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "outputs": [], "source": [ "# add a field of zeros called \"topographic__elevation\" and attach it to the grid nodes\n", - "# save the field to an array with a new name\n", + "# save the field to an array with a new name" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ "z = grid.add_zeros(\"topographic__elevation\", at=\"node\")" ] }, @@ -241,33 +282,55 @@ "metadata": {}, "outputs": [], "source": [ - "# now elevate the upper half of the landscape, following the `node_of_y` method used in part (d)" + "# now elevate the upper half of the landscape" ] }, { "cell_type": "code", "execution_count": null, "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [ "solution" ] }, "outputs": [], "source": [ - "z[grid.y_of_node > 120] += 10" + "z[grid.y_of_node > 120] += 10.0" ] }, { "cell_type": "code", "execution_count": null, "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# now display the landscape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [ "solution" ] }, "outputs": [], "source": [ - "# now display the landscape\n", "grid.imshow(\"topographic__elevation\")" ] }, @@ -282,13 +345,31 @@ "cell_type": "code", "execution_count": null, "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# close left and right boundaries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [ "solution" ] }, "outputs": [], "source": [ - "# close left and right boundaries\n", "grid.status_at_node[grid.nodes_at_left_edge] = grid.BC_NODE_IS_CLOSED\n", "grid.status_at_node[grid.nodes_at_right_edge] = grid.BC_NODE_IS_CLOSED" ] @@ -297,30 +378,58 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Great, we're back where we started with a recently faulted, un-diffused landscape. But now, rather than building our own diffusion model from scratch, we'll let Landlab's `LinearDiffuser` component do the work for us. Create an instance of this component named `diffusion_model` and pass your grid to the component." + "Now, rather than building our own diffusion model from scratch, we'll let Landlab's `LinearDiffuser` component do the work for us. Create an instance of this component named `diffusion` and pass your grid to the component." ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "outputs": [], "source": [ - "# instantiate the linear diffuser component here\n", - "diffusion_model = LinearDiffuser(grid)" + "# instantiate the linear diffuser component here" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ + "diffusion = LinearDiffuser(grid)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Great, we now have an instance of our model. Next, use the `run_one_step` method with a timestep `dt` on `diffusion_model` in a `for` loop in order to evolve our faulted landscape. As in part [Sediment diffusion](#Sediment-diffusion), run the loop for 25 steps. Use the same timestep, `dt`, as defined above. " + "Great, we now have an instance of our component. Next, use the `run_one_step` method with a timestep `dt` on `diffusion` in a `for` loop in order to evolve our faulted landscape. Run the loop for 25 steps. Use a same timestep, `dt`, of 1000.0. " ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "outputs": [], "source": [ "# create your for loop here\n", @@ -331,6 +440,10 @@ "cell_type": "code", "execution_count": null, "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [ "solution" ] @@ -338,27 +451,45 @@ "outputs": [], "source": [ "for _ in range(25):\n", - " diffusion_model.run_one_step(1000.0)" + " diffusion.run_one_step(1000.0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Great, now visualize your landscape to see if it looks similar to the 5-line model you created in part [Sediment diffusion](#Sediment-diffusion)." + "Great, now visualize your landscape to see if it looks as you expect." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# visualize landscape" ] }, { "cell_type": "code", "execution_count": null, "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [ "solution" ] }, "outputs": [], "source": [ - "# visualize landscape\n", "grid.imshow(\"topographic__elevation\")" ] }, @@ -366,7 +497,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Fantastic! Your final output should look very simialr to the diffusion model you created in part [Sediment diffusion](#Sediment-diffusion), but here you can see that using a Landlab component to simulate the diffusion process has simplified your `for` loop even further. You can appreciate how valuable this simplicity is, especially if you wanted to couple several components together (for example, flow routing, fluvial erosion, and hillslope diffusion) in order to evolve a more complex landscape.\n", + "Fantastic! Your final output should look very simialr to the diffusion model you created previously, but here you can see that using a Landlab component to simulate the diffusion process has simplified your `for` loop even further. You can appreciate how valuable this simplicity is, especially if you wanted to couple several components together (for example, flow routing, fluvial erosion, and hillslope diffusion) in order to evolve a more complex landscape.\n", "\n", "As a final, fun exercise, check out the `LinearDiffuser` documentation using `?` once again. See if you can find the list of input parameters. These are listed in the order of the arguments taken by the component; the first one will always be `grid`. " ] @@ -375,11 +506,31 @@ "cell_type": "code", "execution_count": null, "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [] }, "outputs": [], "source": [ - "# check out the optional variables\n", + "# check out the optional variables" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [ + "solution" + ] + }, + "outputs": [], + "source": [ "?LinearDiffuser" ] }, @@ -400,7 +551,7 @@ "source": [ "Congratulations on making it to the end of this tutorial!\n", "\n", - "**Click here for more** Landlab tutorials" + "**Click here for more** Landlab tutorials" ] } ], diff --git a/lessons/landlab/landlab/05-components.ipynb b/lessons/landlab/landlab/05-components.ipynb index d68ca61..759bece 100644 --- a/lessons/landlab/landlab/05-components.ipynb +++ b/lessons/landlab/landlab/05-components.ipynb @@ -13,7 +13,7 @@ "source": [ "## Introduction to Landlab Components\n", "\n", - "A \"potluck\" is a meal in which each guest brings a dish to share. These contributed dishes usually come in one of a few categories: salads, drinks, main dishes, desserts. The meal comes together as a collection of components, each of which contributes to fulfilling one of these basic roles. The resulting meal provides guests with a great variety of choices. A guest can compose their own complete and unique meal by combining their own choices for components. And each guest, while contributing their own particular dish, get to share in the creations of their compatriots. There's a bit of standardization---the dishes are sized to fit on the tables, and their contents are accessible to the usual range of serving utensils---but with that standardization lies a great range of creativity.\n", + "A \"potluck\" is a common American tradition in which each guest brings a dish to share. These contributed dishes usually come in one of a few categories: salads, drinks, main dishes, desserts. The meal comes together as a collection of components, each of which contributes to fulfilling one of these basic roles. The resulting meal provides guests with a great variety of choices. A guest can compose their own complete and unique meal by combining their own choices for components. And each guest, while contributing their own particular dish, gets to share in the creations of their compatriots. There's a bit of standardization---the dishes are sized to fit on the tables, and their contents are accessible to the usual range of serving utensils---but with that standardization lies a great range of creativity.\n", "\n", "Component modeling is a bit like the potluck tradition: one can construct a complete simulation by assembling components to represent the different parts of the system to be modeled. In Landlab, a **component** is a semi-standardized Python *class* that represents a particular process or calculation. Components are not stand-alone programs, but rather are designed to be used within another Python program that creates an integrated model or workflow.\n", "\n", @@ -32,13 +32,18 @@ "Here's an example from the Landlab tutorial *Green-Ampt infiltration and kinematic wave overland flow*. The example code in the tutorial uses two components, `SoilInfiltrationGreenAmpt` and `KinwaveImplicitOverlandFlow`, to calculate overland flow and infiltration across a terrain that is represented by a digital elevation model.\n", "\n", "\n", - "*Figure 2: topography of a gullied area on the Colorado high plains (from Landlab tutorial \"Green-Ampt infiltration and kinematic wave overland flow\").*\n", - "\n" + "*Figure 2: topography of a gullied area on the Colorado high plains (from Landlab tutorial \"Green-Ampt infiltration and kinematic wave overland flow\").*" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "source": [ "\n", "*Figure 3: cumulative infiltration water depth during a simulated five-minute heavy rainfall (from Landlab tutorial \"Green-Ampt infiltration and kinematic wave overland flow\")*\n", @@ -46,18 +51,16 @@ "The following code snippets illustrate how the components are imported...\n", "\n", "```python\n", - "from landlab.components import (\n", - " SoilInfiltrationGreenAmpt,\n", - " KinwaveImplicitOverlandFlow\n", - ")\n", + "from landlab.components import SoilInfiltrationGreenAmpt\n", + "from landlab.components import KinwaveImplicitOverlandFlow\n", "```\n", "\n", "...instantiated...\n", "\n", "```python\n", - "ga = SoilInfiltrationGreenAmpt(grid)\n", + "infiltration = SoilInfiltrationGreenAmpt(grid)\n", "\n", - "kw = KinwaveImplicitOverlandFlow(\n", + "overland_flow = KinwaveImplicitOverlandFlow(\n", " grid, runoff_rate=90.0, roughness=0.1, depth_exp=5.0 / 3.0\n", ")\n", "```\n", @@ -65,19 +68,25 @@ "...and run in a time loop:\n", "\n", "```python\n", - "for i in range(nsteps):\n", - " kw.run_one_step(dt)\n", - " ga.run_one_step(dt)\n", + "for _ in range(nsteps):\n", + " overland_flow.run_one_step(dt)\n", + " infiltration.run_one_step(dt)\n", "```" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "source": [ "### The Landlab component collection\n", "\n", - "The current (spring 2022) collection of components spans a variety of types of process and analysis. You can find a list [in the documentation](https://landlab.readthedocs.io/en/latest/reference/components/index.html).\n", + "The current collection of components spans a variety of types of process and analysis. You can find a list [in the documentation](https://landlab.csdms.io).\n", "\n", "To see a list, you can use the following python commands:" ] @@ -90,7 +99,8 @@ "source": [ "from landlab.components import COMPONENTS\n", "\n", - "[component.__name__ for component in COMPONENTS]" + "for component in COMPONENTS:\n", + " print(component.__name__)" ] }, { @@ -165,7 +175,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "If we want to see the complete documentation, we can also access this information using `?`, similar to how we accessed information from `RasterModelGrid` in part [Explore the Landlab grids](#Explore-the-Landlab-grids)." + "If we want to see the complete documentation, we can also access this information using `?`." ] }, { @@ -186,14 +196,14 @@ "source": [ "Note we haven't needed to instantiate the component in order to access any of this information. Instantiation occurs when we create a unique instance of the component with specific variables and parameter values (just like how we created instances of `RasterModelGrid` above with unique names, dimensions, and grid spacing.) Don't worry if this is confusing right now - it will make sense momentarily. \n", "\n", - "Since we know `LinearDiffuser` requires a topographic elevation field in order to be instantiated, we need to create that field. Recall that `topographic__elevation` is tied to grid nodes, so we actually need to create a grid instance, and add the `topographic__elevation` field onto the grid. This is just like the steps we took in part [Sediment diffusion](#Sediment-diffusion) of this tutorial." + "Since we know `LinearDiffuser` requires a topographic elevation field in order to be instantiated, we need to create that field. Recall that `topographic__elevation` is tied to grid nodes, so we actually need to create a grid instance, and add the `topographic__elevation` field onto the grid." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Create a new grid instance for the `LinearDiffuser` component to run on. Give your new grid a new name (perhaps `new_grid`?), but give it the same dimensions as `mg` (25 x 25, with 10m spacing)." + "Create a new grid instance for the `LinearDiffuser` component to run on. Give you grid 25 rows and colums with a node spacing of 10.0 m." ] }, { @@ -206,12 +216,24 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "cell_type": "markdown", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [ + "solution" + ] + }, "source": [ - "grid = RasterModelGrid((25, 25), 10)" + "
\n", + " 👉 click to see solution\n", + "\n", + "```python\n", + "grid = RasterModelGrid((25, 25), xy_spacing=10)\n", + "```\n", + "
" ] }, { @@ -222,18 +244,44 @@ "\n", "$$\\frac{\\partial z}{\\partial t} = D \\nabla^2 z$$\n", "\n", - "As before, we need some topographic variation in order to drive diffusion. We'll still need to add our `topographic__elevation` field manually, and we'll need to create a \"fault\" on the grid by elevating half of the nodes. Let's do this now, following the format we used in [Sediment diffusion](#Sediment-diffusion)." + "As before, we need some topographic variation in order to drive diffusion. We'll still need to add our `topographic__elevation` field manually, and we'll need to create a \"fault\" on the grid by elevating half of the nodes." ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "outputs": [], "source": [ "# add a field of zeros called \"topographic__elevation\" and attach it to the grid nodes\n", - "# save the field to an array with a new name\n", - "z = grid.add_zeros(\"topographic__elevation\", at=\"node\")" + "# save the field to an array with a new name" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [ + "solution" + ] + }, + "source": [ + "
\n", + " 👉 click to see solution\n", + "\n", + "```python\n", + "z = grid.add_zeros(\"topographic__elevation\", at=\"node\")\n", + "```\n", + "
" ] }, { @@ -242,12 +290,16 @@ "metadata": {}, "outputs": [], "source": [ - "# now elevate the upper half of the landscape, following the `node_of_y` method used in part (d)" + "# now elevate the upper half of the landscape" ] }, { "cell_type": "markdown", "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [ "solution" ] @@ -257,14 +309,33 @@ " 👉 click to see solution\n", "\n", "```python\n", - "z[grid.y_of_node > 120] += 10\n", + "z[grid.y_of_node > 120] += 10.0\n", "```\n", "" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# now display the landscape" + ] + }, { "cell_type": "markdown", "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [ "solution" ] @@ -274,7 +345,6 @@ " 👉 click to see solution\n", "\n", "```python\n", - "# now display the landscape\n", "grid.imshow(\"topographic__elevation\")\n", "```\n", "" @@ -287,9 +357,28 @@ "As in part [Sediment diffusion](#Sediment-diffusion), let's close the left and right grid boundaries." ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# close left and right boundaries" + ] + }, { "cell_type": "markdown", "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [ "solution" ] @@ -299,7 +388,6 @@ " 👉 click to see solution\n", "\n", "```python\n", - "# close left and right boundaries\n", "grid.status_at_node[grid.nodes_at_left_edge] = grid.BC_NODE_IS_CLOSED\n", "grid.status_at_node[grid.nodes_at_right_edge] = grid.BC_NODE_IS_CLOSED\n", "```\n", @@ -310,30 +398,62 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Great, we're back where we started with a recently faulted, un-diffused landscape. But now, rather than building our own diffusion model from scratch, we'll let Landlab's `LinearDiffuser` component do the work for us. Create an instance of this component named `diffusion_model` and pass your grid to the component." + "Now, rather than building our own diffusion model from scratch, we'll let Landlab's `LinearDiffuser` component do the work for us. Create an instance of this component named `diffusion` and pass your grid to the component." ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "outputs": [], "source": [ - "# instantiate the linear diffuser component here\n", - "diffusion_model = LinearDiffuser(grid)" + "# instantiate the linear diffuser component here" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [ + "solution" + ] + }, + "source": [ + "
\n", + " 👉 click to see solution\n", + "\n", + "```python\n", + "diffusion = LinearDiffuser(grid)\n", + "```\n", + "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Great, we now have an instance of our model. Next, use the `run_one_step` method with a timestep `dt` on `diffusion_model` in a `for` loop in order to evolve our faulted landscape. As in part [Sediment diffusion](#Sediment-diffusion), run the loop for 25 steps. Use the same timestep, `dt`, as defined above. " + "Great, we now have an instance of our component. Next, use the `run_one_step` method with a timestep `dt` on `diffusion` in a `for` loop in order to evolve our faulted landscape. Run the loop for 25 steps. Use a same timestep, `dt`, of 1000.0. " ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, "outputs": [], "source": [ "# create your for loop here\n", @@ -343,6 +463,10 @@ { "cell_type": "markdown", "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [ "solution" ] @@ -353,7 +477,7 @@ "\n", "```python\n", "for _ in range(25):\n", - " diffusion_model.run_one_step(1000.0)\n", + " diffusion.run_one_step(1000.0)\n", "```\n", "" ] @@ -362,12 +486,31 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Great, now visualize your landscape to see if it looks similar to the 5-line model you created in part [Sediment diffusion](#Sediment-diffusion)." + "Great, now visualize your landscape to see if it looks as you expect." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [] + }, + "outputs": [], + "source": [ + "# visualize landscape" ] }, { "cell_type": "markdown", "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [ "solution" ] @@ -377,7 +520,6 @@ " 👉 click to see solution\n", "\n", "```python\n", - "# visualize landscape\n", "grid.imshow(\"topographic__elevation\")\n", "```\n", "" @@ -387,7 +529,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Fantastic! Your final output should look very simialr to the diffusion model you created in part [Sediment diffusion](#Sediment-diffusion), but here you can see that using a Landlab component to simulate the diffusion process has simplified your `for` loop even further. You can appreciate how valuable this simplicity is, especially if you wanted to couple several components together (for example, flow routing, fluvial erosion, and hillslope diffusion) in order to evolve a more complex landscape.\n", + "Fantastic! Your final output should look very simialr to the diffusion model you created previously, but here you can see that using a Landlab component to simulate the diffusion process has simplified your `for` loop even further. You can appreciate how valuable this simplicity is, especially if you wanted to couple several components together (for example, flow routing, fluvial erosion, and hillslope diffusion) in order to evolve a more complex landscape.\n", "\n", "As a final, fun exercise, check out the `LinearDiffuser` documentation using `?` once again. See if you can find the list of input parameters. These are listed in the order of the arguments taken by the component; the first one will always be `grid`. " ] @@ -396,12 +538,36 @@ "cell_type": "code", "execution_count": null, "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, "tags": [] }, "outputs": [], "source": [ - "# check out the optional variables\n", - "?LinearDiffuser" + "# check out the optional variables" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "editable": true, + "slideshow": { + "slide_type": "" + }, + "tags": [ + "solution" + ] + }, + "source": [ + "
\n", + " 👉 click to see solution\n", + "\n", + "```python\n", + "?LinearDiffuser\n", + "```\n", + "
" ] }, { @@ -421,7 +587,7 @@ "source": [ "Congratulations on making it to the end of this tutorial!\n", "\n", - "**Click here for more** Landlab tutorials" + "**Click here for more** Landlab tutorials" ] } ],