{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Creating a simple 2D scarp diffusion model with Landlab" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", " For instructions on how to run an interactive IPython notebook, click here: https://github.com/landlab/tutorials/blob/release/README.md
\n", "For the unexpanded version to download and run, click here: https://nbviewer.jupyter.org/github/landlab/tutorials/blob/release/fault_scarp/landlab-fault-scarp-unexpanded.ipynb
\n", "For more Landlab tutorials, click here: https://github.com/landlab/landlab/wiki/Tutorials\n", "
\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This tutorial illustrates how you can use Landlab to construct a simple two-dimensional numerical model on a regular (raster) grid, using a simple forward-time, centered-space numerical scheme. The example is the erosional degradation of an earthquake fault scarp, and which evolves over time in response to the gradual downhill motion of soil. Here we use a simple \"geomorphic diffusion\" model for landform evolution, in which the downhill flow of soil is assumed to be proportional to the (downhill) gradient of the land surface multiplied by a transport coefficient.\n", "\n", "We start by importing the NumPy library:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will create a grid for our model using Landlab's *RasterModelGrid* class, which we need to import." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from landlab import RasterModelGrid" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The syntax in the next line says: create a new *RasterModelGrid* object called **mg**, with 25 rows, 40 columns, and a grid spacing of 10 m." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "mg = RasterModelGrid((25, 40), 10.0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note the use of object-oriented programming here. `RasterModelGrid` is a class; `mg` is a particular instance of that class, and it contains all the data necessary to fully describe the topology and geometry of this particular grid.\n", "\n", "Next we'll add a *data field* to the grid, to represent the elevation values at grid nodes. The \"dot\" syntax below indicates that we are calling a function (or *method*) that belongs to the *RasterModelGrid* class, and will act on data contained in **mg**. The arguments indicate that we want the data elements attached to grid nodes (rather than links, for example), and that we want to name this data field `topographic__elevation`. The `add_zeros` method returns the newly created NumPy array." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "z = mg.add_zeros('node', 'topographic__elevation')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The above line of code creates space in memory to store 1,000 floating-point values, which will represent the elevation of the land surface at each of our 1,000 grid nodes.\n", "\n", "Let's take a look at the grid we've created. To do so, we'll use the Matplotlib graphics library (imported under the name `plt`). We also have to tell the Notebook to display plots right here on the page." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's plot the positions of all the grid nodes. The nodes' *(x,y)* positions are stored in the arrays `mg.x_of_node` and `mg.y_of_node`, respectively." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(mg.x_of_node, mg.y_of_node, '.')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we bothered to count, we'd see that there are indeed 1,000 grid nodes, and a corresponding number of `z` values:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1000" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now for some tectonics. Let's say there's a fault trace that angles roughly east-northeast. We can describe the trace with the equation for a line. One trick here: by using `mg.x_of_node`, in the line of code below, we are calculating a *y* (i.e., north-south) position of the fault trace for each grid node---meaning that this is the *y* coordinate of the trace at the *x* coordinate of a given node." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "fault_trace_y = 50.0 + 0.25 * mg.x_of_node" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here comes the earthquake. For all the nodes north of the fault (i.e., those with a *y* coordinate greater than the corresponding *y* coordinate of the fault trace), we'll add elevation equal to 10 meters plus a centimeter for every meter east along the grid (just to make it interesting):" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "z[mg.y_of_node > fault_trace_y] += 10.0 + 0.01 * mg.x_of_node[mg.y_of_node > fault_trace_y]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(A little bit of Python under the hood: the statement `mg.y_of_node > fault_trace_y` creates a 1000-element long boolean array; placing this within the index brackets will select only those array entries that correspond to `True` in the boolean array)\n", "\n", "Let's look at our newly created initial topography using Landlab's *imshow_node_grid* plotting function (which we first need to import)." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXEAAADtCAYAAABJVEUoAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAU3UlEQVR4nO3df6xfdX3H8eeLgvzQMqkFgm0zmKk/gM3KOmRjUxTRimbFZCxl0TQbWf0DnRqzCTMZ7g8SEhW3xMl2FUZVBDuVQBxBKpMQEwVaZEopjE6wFDpqZU42F6C9r/3xPdd9W+733nO+Ped8z7m+HsnJ93vO9/x499N73/fz/ZzP+Xxkm4iI6KfDJh1ARESML0k8IqLHksQjInosSTwioseSxCMieuzwSQcQEdEXa9as8d69e0vtu3Xr1m/YXtNwSEniERFl7d27ly1btpTaV9LShsMBksQjIirq1rM1SeIRERXY05MO4QBJ4hERpZnUxCMieqxrQ5UkiUdEVJIkHhHRY0niERG9leaUiIjeMpDeKRERvWSnJh4R0XNJ4hERPZYkHhHRU05zSkREv+XGZkREb6UmHhHRWxk7JSKi59KcEhHRW2lOiYjotSTxiIieciaFiIjot9TEIyJ6LEk8IqKXMgBWRESvpZ94rZYsOdYrlp8w+4dSrdcafbpxrzPOcfUeM3cR1Vt+45xPY/8f9jn2+mIY/7hx/r11x3Aox81u69ate20ff6jnsffXEU5tep3EVyw/gdtuvWrWz3TYiB+AOX4u5vrF02GHjfhk0RznG3UMSKOOmyvpznWtUZ+NE8PcsY+KcfzzzX7c3OU3zvnmSgrjXWvUv3nu+OY636gY6/5/HLdsR/3fj3u+6seNE9/gOP1ojgMr6FZNfK7SiIiIAwxGMSyzzEfStZL2SHpgaNvHJT0k6fuSbpL00vnOkyQeEVGJSy7zug5Yc9C2zcDptn8D+DfgsvlOkiQeEVFJPUnc9l3A0wdtu932vmL1u8Dy+c7T6zbxiIi2VehiuFTSlqH1KdtTFS71J8CX59spSTwiojQDpXun7LW9epyrSPoosA+4fr59k8QjIipo+mEfSeuBdwLnusTFksQjIippLolLWgN8BHij7Z+XOSY3NiMiKqnnxqakG4DvAK+StEvSxcCngcXAZkn3S/r7+c6TmnhEREll+4CXPNdFs2y+pup5ksQjIirp1hObSeIRERVk7JSIiN7KKIYRET2XJB4R0VuZYzMiotdSE4+I6KnMdh8R0XNJ4hERvZSJkiMiei1dDCMiei5JPCKit3JjMyKit0xubEZE9Fhq4hERvZY28YiIHutWEm9sZh9JKyR9S9J2SdskfaDYvkTSZkmPFK/HDR1zmaQdkh6W9LamYouIGM/gic0yS1uanJ5tH/Bh268BzgIukXQqcClwh+2VwB3FOsVn64DTgDXAZyQtajC+iIgx1DM9W10aS+K2d9u+r3j/DLAdWAasBTYWu20ELijerwVutP2s7UeBHcCZTcUXEVGdsfeXWtrSykTJkk4GXgfcDZxoezcMEj1wQrHbMuDxocN2FdsiIjqkWzXxxm9sSnoJ8FXgg7Z/JmnkrrNse0FJSNoAbABYtuz4usKMiJhXF8dOabQmLukIBgn8ettfKzY/Jemk4vOTgD3F9l3AiqHDlwNPHnxO21O2V9te/bIlxzYXfETEbAaZfP6lJU32ThFwDbDd9lVDH90CrC/erwduHtq+TtKRkk4BVgL3NBVfRMQkSbpW0h5JDwxtG9l7b5Qma+JnA+8B3izp/mI5H7gSOE/SI8B5xTq2twGbgAeB24BL3LVppSPil56nXWop4ToGPfGGzdp7by6NtYnb/jazt3MDnDvimCuAK5qKKSLi0Li2NnHbdxWdPoatBc4p3m8E7gQ+Mtd58sRmRERZ1TqeLJW0ZWh9yvbUPMcc0HtP0gnz7J8kHhFRSfma+F7bq5sMBVrqJx4RsVA03DllVO+9kZLEIyKqaDaLj+q9N1KaUyIiKqjrxqakGxjcxFwqaRdwOYPeepskXQzsBC6c7zxJ4hERZdX4RL3ti0Z8NGvvvVGSxCMiqujYY/dJ4hERJZnO5fAk8YiI8todF6WMJPGIiAo6lsOTxCMiSjNQblyU1iSJR0RU4I5NlJwkHhFRRbdyeJJ4REQlHWsUTxKPiKigYzk8STwiojRTdsKH1iSJR0SUln7iERH91q0cniQeEVHW4LH7bmXxJPGIiLJqHMWwLkniEREVpCYeEdFn6Z0SEdFfHauIJ4lHRJTWwQHFk8QjIqroVg5vbrZ7SddK2iPpgaFtH5P0hKT7i+X8oc8uk7RD0sOS3tZUXBER4zN2uaUtTdbErwM+DXz+oO2fsv2J4Q2STgXWAacBLwe+KemVtvc3GF9ERGVde+y+sZq47buAp0vuvha40fazth8FdgBnNhVbRMRYXGFpSWNJfA7vk/T9ornluGLbMuDxoX12FdteQNIGSVskbfnJ0z9rOtaIiAPZ5ZZ5SPqQpG2SHpB0g6Sjxgmn7SR+NfAKYBWwG/hksV2z7DtrKdiesr3a9uqXLTm2mSgjImYx0znlUHO4pGXAnwGrbZ8OLGLQpFxZq71TbD81817SZ4GvF6u7gBVDuy4HnmwxtIiIcuq7aXk4cLSk54FjGDPntVoTl3TS0Oq7gJmeK7cA6yQdKekUYCVwT5uxRUSUUUdN3PYTwCeAnQxaJf7L9u3jxNNYTVzSDcA5wFJJu4DLgXMkrWLwreQx4L0AtrdJ2gQ8COwDLknPlIiF75RFL5p0CNXYVR67Xyppy9D6lO0pgOJ+4FrgFOCnwD9JerftL1YNqbEkbvuiWTZfM8f+VwBXNBVPREQdKvQB32t79YjP3gI8avvHAJK+BvwO0J0kHhGxINXTJr4TOEvSMcD/AucCW+Y+ZHZJ4hERFdSRw23fLekrwH0MmpC/B0yNc64k8YiIsmocAMv25QzuFR6SJPGIiCq69dR9knhERBVdGzslSTwiDvCKIxZPOoTOMu2OUFhGknhERFmZKDkioudSE4+I6K80p0RE9FhubEZE9JWB6UkHcaAk8YgeeOVRJ0w6hJjRseaUkUPRSrpV0snthRIR0X01TexTm7nGE78OuF3SRyUd0VI8EREdVjKDd2G2e9ubJP0z8FfAFklfYKg1yPZVLcQXEdEdLdeyy5ivTfx54H+AI4HFdK5JPyKiZdPdSoMjk7ikNcBVDKZOO8P2z1uLKiKigwy4Wzl8zpr4R4ELbW9rK5iIiE6rcSjauszVJv57bQYS0UevPmbFpEOIlnUsh6efeEREJR3L4kniERGlda97SpJ4RERZBu9PEo+I6K2OVcSTxCMiKulYFp/rsftDIulaSXskPTC0bYmkzZIeKV6PG/rsMkk7JD0s6W1NxRURMTYPxhMvs7SlyZr4dcCngc8PbbsUuMP2lZIuLdY/IulUYB1wGvBy4JuSXml7f4PxxQJ12uKVkw4hFrKOPezTWE3c9l3A0wdtXgtsLN5vBC4Y2n6j7WdtPwrsAM5sKraIiHEMnth0qaUMSS+V9BVJD0naLum3q8bUdpv4ibZ3A9jeLWlmkORlwHeH9ttVbHsBSRuADQDLlh3fYKgREQexod6Zff4WuM32H0h6EXBM1RM0VhOvSLNsm7WkbE/ZXm179cuWHNtwWBERB6qrTVzSscAbgGuK8z5n+6dV42k7iT8l6SSA4nVPsX0XMPz88nLgyZZji4iYn0susFTSlqFlw0Fn+jXgx8A/SvqepM9JenHVcNpO4rcA64v364Gbh7avk3SkpFOAlcA9LccWETG/8pNC7J1pNSiWqYPOdDhwBnC17dcxGPb70qrhNNYmLukG4BwGf412AZcDVwKbJF0M7AQuBLC9TdIm4EFgH3BJeqYsLL/+K6+ddAgRh861zna/C9hl++5i/St0KYnbvmjER+eO2P8K4Iqm4omIqENdSdz2f0h6XNKrbD/MIDc+WPU8eWIzIqIsU3c/8fcD1xc9U34I/HHVEySJR0SUVu/TmLbvB1YfyjmSxCMiqqi3n/ghSxKPiKiiWzk8STwioiwXA2B1SZL4L7FVS14/6RAieieTQkRE9JVJm3hERH+1O1Z4GUniERFVdGw88STxiIgKUhOPiOgrA7mxGRHRX6mJx5x+8/g3TzqEiBjBJIlHRPRax+5rJolHRJRWcuq1NiWJR0RUkCQeEdFTgwc2k8QjInorNfGe+q0T3zHpECKiA5LEIyJ6rFspPEk8IqI0p3dKRES/5cZmRESPpSYeEdFjXUvih006gIiIvpgZO6XMUoakRZK+J+nr48Y0kZq4pMeAZ4D9wD7bqyUtAb4MnAw8Bvyh7f+c6zwP/eDfOWvF2maDjYgYUvPYKR8AtgPHjnuCSdbE32R7le3VxfqlwB22VwJ3FOsREd1RshZepiYuaTnwDuBzhxJSl5pT1gIbi/cbgQsmGEtExAsYmJ6eLrUASyVtGVo2HHS6vwH+gkOs3E/qxqaB2yUZ+AfbU8CJtncD2N4t6YTZDiwKYgPAoraijYgoVLituXeopeEAkt4J7LG9VdI5hxLPpJL42bafLBL1ZkkPlT2wSPhTAEcO/ghERLSmpt4pZwO/L+l84CjgWElftP3uqieaSHOK7SeL1z3ATcCZwFOSTgIoXvdMIraIiLnU0SZu+zLby22fDKwD/mWcBA4TSOKSXixp8cx74K3AA8AtwPpit/XAzW3HFhExF9tMl1zaMonmlBOBmyTNXP9Ltm+TdC+wSdLFwE7gwgnEFhExp7rTs+07gTvHPb71JG77h8BrZ9n+E+DctuOJiKii6HnSGXnsPiKigq49dp8kHhFRUqZni4jos4wnHhHRb91K4UniERGlGdifG5sREf2V5pSIiB5LEo+I6KlMlBwR0XPdahFPEo+IqCQ18YiInkrvlIiInktNPCKir3JjMyKivzJ2SkREz6UmHhHRY0niERE9ZTu9UyIi+ixt4hERPZbmlIiInkrvlIiInutaTfywSQcQEdEbxY3NMst8JK2Q9C1J2yVtk/SBcUJKTTwioqSam1P2AR+2fZ+kxcBWSZttP1jlJEniEREV1NWcYns3sLt4/4yk7cAyoFIS71xziqQ1kh6WtEPSpZOOJyLiF2ymSy5VSDoZeB1wd9WQOlUTl7QI+DvgPGAXcK+kW6p+vYiIaIKpVBNfKmnL0PqU7amDd5L0EuCrwAdt/6xqTJ1K4sCZwA7bPwSQdCOwlopfLyIimlKhlr3X9uq5dpB0BIMEfr3tr40TT9eS+DLg8aH1XcDrh3eQtAHYALCovbgiImqdFEKSgGuA7bavGvc8XWsT1yzbDvizZ3vK9mrbq5PEI6JV9baJnw28B3izpPuL5fyqIXWtJr4LWDG0vhx4ckKxRES8QF1dDG1/m9krrpV0LYnfC6yUdArwBLAO+KPJhhQRMWDAGcVwNNv7JL0P+AaDJu9rbW8btf9zsHcn/Gho01Jgb8NhzqcLMUA34uhCDNCNOLoQA3QjjknF8Kt1nCRjp8zD9q3ArSX3PX54XdKW+e4GN60LMXQlji7E0JU4uhBDV+LoQgxjG6MPeNM6l8QjIrrKwL79+ycdxgGSxCMiKujaKIYLLYm/4GmoCehCDNCNOLoQA3Qjji7EAN2IowsxjMUdbE5R1/6qRER01fGLF/uCM84ote/n7rpraxtt/wutJh4R0ZjM7BMR0Wd2525sdu2x+7FMcvhaSY9J+kHxyOyWYtsSSZslPVK8HlfzNa+VtEfSA0PbRl5T0mVF2Tws6W0Nx/ExSU/M9hhxE3GMmh2lzfKYI4a2y+IoSfdI+tcijr8utrdZFqNiaLUsmmJgv11qaUvvk/jQ8LVvB04FLpJ0asthvMn2qqH2r0uBO2yvBO4o1ut0HbDmoG2zXrMoi3XAacUxnynKrKk4AD5VlMeqot9/k3HMzI7yGuAs4JLiWm2Wx6gYoN2yeBZ4s+3XAquANZLOot2yGBUDtFsWjZmeni61tKX3SZyh4WttPwfMDF87SWuBjcX7jcAFdZ7c9l3A0yWvuRa40fazth8FdjAos6biGKWROGzvtn1f8f4ZYGZ2lNbKY44YRmmqLGz7v4vVI4rFtFsWo2IYpbGfzya43gGwarEQkvhsw9fO9QtUNwO3S9paDJMLcGIx9dLMFEwntBDHqGtOonzeJ+n7RXPLzFf3xuPQgbOjTKQ89MIZWlotC0mLJN0P7AE22269LEbEABP6uahbauL1m3f42oadbfsMBs05l0h6Q4vXLqPt8rkaeAWDr9K7gU+2EYfKz47SWByzxNB6Wdjeb3sVgxFAz5R0+lwhNxHHiBgm8nNRt5nxxOuY7b4uCyGJT3T4WttPFq97gJsYfBV8StJJAMXrnhZCGXXNVsvH9lPFL/E08Fn+/6txY3Fo9tlRWi2P2WKYRFnMsP1T4E4G7cwT+dkYjmGSZVEn2zy/f3+ppS0LIYn/YvhaSS9icJPkljYuLOnFkhbPvAfeCjxQXH99sdt64OYWwhl1zVuAdZKO1GCI35XAPU0FMZMsCu9iUB6NxSGNnB2ltfIYFcMEyuJ4SS8t3h8NvAV4iHbLYtYY2i6LJnWtOaX3/cSrDl9bsxOBmwa/wxwOfMn2bZLuBTZJuhjYCVxY50Ul3QCcw2Ai1l3A5cCVs13T9jZJmxjMU7oPuMR2LdWEEXGcI2kVg2+ejwHvbTiOmdlRflC0wwL8Je2Wx6gYLmq5LE4CNha9Ow4DNtn+uqTv0F5ZjIrhCy2XRSNst9pUUkYeu4+IKOnYo4/2WaecUmrfzdu357H7iIhO6WBNPEk8IqIkQ6vt3WUkiUdElGSbZ597btJhHCBJPCKiJNvsS008IqK/9mcUw4j6aTCS4KOSlhTrxxXrtcxwHgHg6Wmef/bZUst8VNPoq6mJx4Jg+3FJVzPoH76heJ2y/aPJRhYLiW2er6FNfGj01fMYPLV6r6RbbD9Y9VxJ4rGQfArYKumDwO8C759wPLHATE9P8/NnnqnjVL8YfRVA0szoq0ni8cvL9vOS/hy4DXhrMTRxRG2eg2/shKUldz9KxUQxhSnbM5NEzzZ64+vHiSlJPBaatzMYJe90YPOEY4kFxvZsk6CMo7bRG3NjMxaMYmyO8xjMrvOhgwZdiuiS2kZvTBKPBaEYSfBqBmN57wQ+DnxislFFjFTb6KtJ4rFQ/Cmw0/ZME8pngFdLeuMEY4qYle19wMzoq9sZjPY41uirGcUwIqLHUhOPiOixJPGIiB5LEo+I6LEk8YiIHksSj4josSTxiIgeSxKPiOix/wPs2zcbELNesAAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "from landlab.plot.imshow import imshow_grid\n", "imshow_grid(mg, 'topographic__elevation')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To finish getting set up, we will define two parameters: the transport (\"diffusivity\") coefficient, `D`, and the time-step size, `dt`. (The latter is set using the Courant condition for a forward-time, centered-space finite-difference solution; you can find the explanation in most textbooks on numerical methods)." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2000.0" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "D = 0.01 # m2/yr transport coefficient\n", "dt = 0.2 * mg.dx * mg.dx / D\n", "dt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Boundary conditions: for this example, we'll assume that the east and west sides are closed to flow of sediment, but that the north and south sides are open. (The order of the function arguments is east, north, west, south)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "mg.set_closed_boundaries_at_grid_edges(True, False, True, False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "*A note on boundaries:* with a Landlab raster grid, all the perimeter nodes are boundary nodes. In this example, there are 24 + 24 + 39 + 39 = 126 boundary nodes. The previous line of code set those on the east and west edges to be **closed boundaries**, while those on the north and south are **open boundaries** (the default). All the remaining nodes are known as **core** nodes. In this example, there are 1000 - 126 = 874 core nodes:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "874" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(mg.core_nodes)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One more thing before we run the time loop: we'll create an array to contain soil flux. In the function call below, the first argument tells Landlab that we want one value for each grid link, while the second argument provides a name for this data *field*:" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "qs = mg.add_zeros('link', 'sediment_flux')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And now for some landform evolution. We will loop through 25 iterations, representing 50,000 years. On each pass through the loop, we do the following:\n", "\n", "1. Calculate, and store in the array `g`, the gradient between each neighboring pair of nodes. These calculations are done on **links**. The gradient value is a positive number when the gradient is \"uphill\" in the direction of the link, and negative when the gradient is \"downhill\" in the direction of the link. On a raster grid, link directions are always in the direction of increasing $x$ (\"horizontal\" links) or increasing $y$ (\"vertical\" links).\n", "\n", "2. Calculate, and store in the array `qs`, the sediment flux between each adjacent pair of nodes by multiplying their gradient by the transport coefficient. We will only do this for the **active links** (those not connected to a closed boundary, and not connecting two boundary nodes of any type); others will remain as zero.\n", "\n", "3. Calculate the resulting net flux at each node (positive=net outflux, negative=net influx). The negative of this array is the rate of change of elevation at each (core) node, so store it in a node array called `dzdt'.\n", "\n", "4. Update the elevations for the new time step." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "for i in range(25):\n", " g = mg.calc_grad_at_link(z)\n", " qs[mg.active_links] = -D * g[mg.active_links]\n", " dzdt = -mg.calc_flux_div_at_node(qs)\n", " z[mg.core_nodes] += dzdt[mg.core_nodes] * dt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's look at how our fault scarp has evolved." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "imshow_grid(mg, 'topographic__elevation')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that we have just created and run a 2D model of fault-scarp creation and diffusion with fewer than two dozen lines of code. How long would this have taken to write in C or Fortran?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Complete code can be found here: https://github.com/landlab/tutorials/blob/release/fault_scarp/landlab-fault-scarp.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What's going on under the hood?\n", "\n", "This example uses a finite-volume numerical solution to the 2D diffusion equation. The 2D diffusion equation in this case is derived as follows. Continuity of mass states that:\n", "\n", "$\\frac{\\partial z}{\\partial t} = -\\nabla \\cdot \\mathbf{q}_s$,\n", "\n", "where $z$ is elevation, $t$ is time, the vector $\\mathbf{q}_s$ is the volumetric soil transport rate per unit width, and $\\nabla$ is the divergence operator (here in two dimensions). (Note that we have omitted a porosity factor here; its effect will be subsumed in the transport coefficient). The sediment flux vector depends on the slope gradient:\n", "\n", "$\\mathbf{q}_s = -D \\nabla z$,\n", "\n", "where $D$ is a transport-rate coefficient---sometimes called *hillslope diffusivity*---with dimensions of length squared per time. Combining the two, and assuming $D$ is uniform, we have a classical 2D diffusion equation:\n", "\n", "$\\frac{\\partial z}{\\partial t} = -\\nabla^2 z$.\n", "\n", "For the numerical solution, we discretize $z$ at a series of *nodes* on a grid. The example in this notebook uses a Landlab *RasterModelGrid*, in which every interior node sits inside a cell of width $\\Delta x$, but we could alternatively have used any grid type that provides nodes, links, and cells.\n", "\n", "The gradient and sediment flux vectors will be calculated at the *links* that connect each pair of adjacent nodes. These links correspond to the mid-points of the cell faces, and the values that we assign to links represent the gradients and fluxes, respectively, along the faces of the cells.\n", "\n", "The flux divergence, $\\nabla \\mathbf{q}_s$, will be calculated by summing, for every cell, the total volume inflows and outflows at each cell face, and dividing the resulting sum by the cell area. Note that for a regular, rectilinear grid, as we use in this example, this finite-volume method is equivalent to a finite-difference method.\n", "\n", "To advance the solution in time, we will use a simple explicit, forward-difference method. This solution scheme for a given node $i$ can be written:\n", "\n", "$\\frac{z_i^{t+1} - z_i^t}{\\Delta t} = -\\frac{1}{A_i} \\sum\\limits_{j=1}^{N_i} \\delta (l_{ij}) q_s (l_{ij}) \\lambda(l_{ij})$.\n", "\n", "Here the superscripts refer to time steps, $\\Delta t$ is time-step size, $q_s(l_{ij})$ is the sediment flux per width associated with the link that crosses the $j$-th face of the cell at node $i$, $\\lambda(l_{ij})$ is the width of the cell face associated with that link ($=\\Delta x$ for a regular uniform grid), and $N_i$ is the number of active links that connect to node $i$. The variable $\\delta(l_{ij})$ contains either +1 or -1: it is +1 if link $l_{ij}$ is oriented away from the node (in which case positive flux would represent material leaving its cell), or -1 if instead the link \"points\" into the cell (in which case positive flux means material is entering).\n", "\n", "To get the fluxes, we first calculate the *gradient*, $G$, at each link, $k$:\n", "\n", "$G(k) = \\frac{z(H_k) - z(T_k)}{L_k}$.\n", "\n", "Here $H_k$ refers the *head node* associated with link $k$, $T_k$ is the *tail node* associated with link $k$. Each link has a direction: from the tail node to the head node. The length of link $k$ is $L_k$ (equal to $\\Delta x$ is a regular uniform grid). What the above equation says is that the gradient in $z$ associated with each link is simply the difference in $z$ value between its two endpoint nodes, divided by the distance between them. The gradient is positive when the value at the head node (the \"tip\" of the link) is greater than the value at the tail node, and vice versa.\n", "\n", "The calculation of gradients in $z$ at the links is accomplished with the `calc_grad_at_link` function. The sediment fluxes are then calculated by multiplying the link gradients by $-D$. Once the fluxes at links have been established, the `calc_flux_div_at_node` function performs the summation of fluxes." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Click here for more Landlab tutorials" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.7" } }, "nbformat": 4, "nbformat_minor": 1 }