{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# BEE 4750 Homework 3: Discretization, Numerical Convergence, and\n",
        "\n",
        "Simulation\n",
        "\n",
        "**Name**:\n",
        "\n",
        "**ID**:\n",
        "\n",
        "> **Due Date**\n",
        ">\n",
        "> Thursday, 09/24/26, 9:00pm\n",
        "\n",
        "## Overview\n",
        "\n",
        "### Instructions\n",
        "\n",
        "- Problem 1 asks you to discretize several systems models by hand and\n",
        "  reason about characteristic timescales and convergence, without\n",
        "  writing any code.\n",
        "- Problem 2 asks you to extend the shallow lake model from class to\n",
        "  include a sediment phosphorus stock, then use numerical simulation to\n",
        "  check convergence and study the resulting long-term lake dynamics.\n",
        "\n",
        "### Load Environment\n",
        "\n",
        "The following code loads the environment and makes sure all needed\n",
        "packages are installed. This should be at the start of most Julia\n",
        "scripts."
      ],
      "id": "89b38c75-f994-44ca-865b-3cd8353d66fd"
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {},
      "outputs": [],
      "source": [
        "import Pkg\n",
        "Pkg.activate(@__DIR__)\n",
        "Pkg.instantiate()"
      ],
      "id": "2"
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {},
      "outputs": [],
      "source": [
        "using Plots\n",
        "using LaTeXStrings"
      ],
      "id": "4"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Problems (Total: 50 Points)"
      ],
      "id": "c7fea456-9887-453c-a367-7a526bcd5ce6"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Problem 1 (15)\n",
        "\n",
        "For each of the following systems models, (i) write the forward Euler\n",
        "update rule, (ii) find the (local) characteristic timescale and use it\n",
        "to evaluate whether the given step size $\\Delta t$ is a reasonable\n",
        "choice, and (iii) use the given error to predict the error at the new\n",
        "step size, assuming the method is well into its first-order convergence\n",
        "regime."
      ],
      "id": "d03debd1-c820-40db-8392-2ca27247fbee"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "#### Problem 1.1 (4)\n",
        "\n",
        "$$\\frac{dC}{dt} = 5 - 0.25C$$\n",
        "\n",
        "1.  Write the forward Euler update rule for $C(t + \\Delta t)$.\n",
        "\n",
        "2.  Find the characteristic timescale of this system. Is $\\Delta t = 1$\n",
        "    a reasonable starting choice of step size? Justify your answer.\n",
        "\n",
        "3.  A forward Euler simulation of this system has an error of $0.6$ at\n",
        "    $\\Delta t = 2$. What error would you expect at $\\Delta t = 1$?"
      ],
      "id": "2e684bac-5a26-4cb4-bcc6-5c2a0d340e0d"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "#### Problem 1.2 (5)\n",
        "\n",
        "A well-mixed holding tank has volume $V = 200\\ \\text{m}^3$ and a\n",
        "through-flow of $Q = 50\\ \\text{m}^3/\\text{yr}$ carrying an inflow\n",
        "concentration $C_\\text{in} = 2\\ \\text{mg/L}$. A pollutant in the tank\n",
        "also decays at a first-order rate $k = 0.3\\ \\text{yr}^{-1}$. The\n",
        "concentration in the tank, $C(t)$, is governed by\n",
        "\n",
        "$$\\frac{dC}{dt} = \\frac{Q}{V}\\left(C_\\text{in} - C\\right) - kC.$$\n",
        "\n",
        "1.  Write the forward Euler update rule for $C(t + \\Delta t)$.\n",
        "\n",
        "2.  Find the characteristic timescale of this system. Is\n",
        "    $\\Delta t = 1\\ \\text{yr}$ a reasonable starting choice of step size?\n",
        "    Justify your answer.\n",
        "\n",
        "3.  A forward Euler simulation of this system has an error of $0.8$ at\n",
        "    $\\Delta t = 1.6\\ \\text{yr}$. What error would you expect at\n",
        "    $\\Delta t = 0.4\\ \\text{yr}$?"
      ],
      "id": "aaef306c-62bd-4e5a-96b6-c090397617e9"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "#### Problem 1.3 (6)\n",
        "\n",
        "$$\\frac{dx}{dt} = 3 - 0.5x^2, \\qquad x \\geq 0$$\n",
        "\n",
        "1.  Write the forward Euler update rule for $x(t + \\Delta t)$.\n",
        "\n",
        "2.  This system’s rate of change depends on the state $x$, so there is\n",
        "    no single characteristic timescale for the whole system — only a\n",
        "    *local* one. Find the system’s equilibrium (be careful about the\n",
        "    problem domain), then linearize near it to find the local feedback\n",
        "    gain and the local characteristic timescale there. Is\n",
        "    $\\Delta t = 0.5$ a reasonable starting choice of step size near this\n",
        "    equilibrium? Justify your answer.\n",
        "\n",
        "3.  A forward Euler simulation of this system has an error of $1.5$ at\n",
        "    $\\Delta t = 0.3$. What error would you expect at $\\Delta t = 0.1$?"
      ],
      "id": "da3d027a-9680-48eb-b49e-18aa594d3817"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Problem 2 (35)\n",
        "\n",
        "In class, we modeled a shallow lake’s phosphorus (P) concentration with\n",
        "\n",
        "$$\\frac{dP}{dt} = L - sP + R(P),$$\n",
        "\n",
        "treating the maximum sediment release rate $r$ (inside $R(P)$) as a\n",
        "fixed constant. A more advanced version of this model could be built by\n",
        "noting that $r$ is really $\\kappa M$, where $M$ is a **sediment\n",
        "phosphorus pool** — a slowly-filling stock.\n",
        "\n",
        "The two-stock model splits the single loss rate $s$ into two pieces\n",
        "(outflow/permanent burial, $s_\\text{out}$, and transfer into the\n",
        "sediment, $h$), and adds a second state variable $M(t)$ for the sediment\n",
        "pool:\n",
        "\n",
        "$$\\begin{aligned}\n",
        "\\frac{dP}{dt} &= L - s_\\text{out}P - hP + \\kappa M\\,\\frac{P^q}{m^q + P^q} \\\\[0.3em]\n",
        "\\frac{dM}{dt} &= hP - bM - \\kappa M\\,\\frac{P^q}{m^q + P^q}\n",
        "\\end{aligned}$$\n",
        "\n",
        "where $b$ is the rate at which sediment P is permanently buried. Use the\n",
        "parameter values in\n",
        "<a href=\"#tbl-lake-params\" class=\"quarto-xref\">Table 1</a> for the rest\n",
        "of this problem.\n",
        "\n",
        "| Parameter | Meaning | Value |\n",
        "|:------------------------:|:--------------------|:------------------------:|\n",
        "| $s_\\text{out}$ | P outflow/permanent burial rate (from the water column) | $0.3\\ \\text{yr}^{-1}$ |\n",
        "| $h$ | P transfer rate into the sediment | $0.3\\ \\text{yr}^{-1}$ |\n",
        "| $b$ | sediment P burial rate | $0.02\\ \\text{yr}^{-1}$ |\n",
        "| $\\kappa$ | sediment recycling rate coefficient | $0.15\\ \\text{yr}^{-1}$ |\n",
        "| $m$ | P concentration at half-maximum sediment release | $25\\ \\mu\\text{g}/\\text{L}$ |\n",
        "| $q$ | steepness of the sediment release response | $8$ |\n",
        "\n",
        "Table 1: Parameters for the two-stock lake model.\n",
        "\n",
        "Assume the lake starts with no phosphorus anywhere in the system,\n",
        "$P(0) = M(0) = 0$."
      ],
      "id": "b988e8e1-056a-4208-b1af-a76dd40f1ae1"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "#### Problem 2.1 (5)\n",
        "\n",
        "Derive the forward Euler update rules for $P(t+\\Delta t)$ and\n",
        "$M(t + \\Delta t)$. Note that these two updates are coupled: at each\n",
        "step, both updates use the *current* $P(t)$ and $M(t)$ (not the\n",
        "newly-updated value of one when computing the other)."
      ],
      "id": "ba89550f-6abe-40ec-81f8-16132f34c531"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "#### Problem 2.2 (13)\n",
        "\n",
        "Implement your update rules from Problem 2.1 and use them to simulate\n",
        "the lake under a loading of\n",
        "$L = 10\\ \\mu\\text{g}/(\\text{L}\\cdot\\text{yr})$, starting from\n",
        "$P(0) = M(0) = 0$.\n",
        "\n",
        "Two different quantities have to be “large enough” here, for two\n",
        "different reasons:\n",
        "\n",
        "- the **simulation horizon** $T$ has to be long enough for the slow\n",
        "  sediment stock $M$ to fill. Its characteristic timescale is\n",
        "  $1/b = 1/0.02 = 50\\ \\text{yr}$, so use $T = 300\\ \\text{yr}$ — six of\n",
        "  those timescales. You will reuse this same run in Problem 2.3.\n",
        "- the **step size** $\\Delta t$ is what you are actually checking for\n",
        "  numerical convergence, at that fixed $T$.\n",
        "\n",
        "Run a convergence study on $P(30)$, the phosphorus concentration thirty\n",
        "years in. Build a reference solution at a very fine step size (smaller\n",
        "than you think you might need), then test a sequence of\n",
        "successively-halved, coarser step sizes against it. Here is a starting\n",
        "point:\n",
        "\n",
        "``` julia\n",
        "function simulate_lake(loading, horizon, step)\n",
        "    # TODO: forward Euler on P and M, using your update rules from Problem 2.1.\n",
        "    # Both updates use the *current* P and M, not a partly-updated value.\n",
        "    # Return the full P trajectory as a vector, one entry per step taken.\n",
        "    error(\"simulate_lake has not been written yet -- replace this line with your loop\")\n",
        "end\n",
        "\n",
        "step_reference = 0.001                        # 300,000 steps at T = 300; a few seconds\n",
        "P_reference = simulate_lake(10.0, 300.0, step_reference)\n",
        "P30_reference = P_reference[Int(30 / step_reference)]     # the entry at t = 30 yr\n",
        "```\n",
        "\n",
        "Report a table of your step sizes, the resulting $P(30)$, the error\n",
        "relative to your reference, and the empirical order of convergence\n",
        "between successive refinements. Make a log-log plot of error\n",
        "vs. $\\Delta t$, and state which step size you will use for the rest of\n",
        "this problem and why.\n",
        "\n",
        "> **A step size that is too large will not just be inaccurate**\n",
        ">\n",
        "> Forward Euler can blow up entirely, rather than merely losing\n",
        "> accuracy, when the step is too large for the *fastest* process in the\n",
        "> system. Here that is $P$ itself, with a timescale of\n",
        "> $1/(s_\\text{out} + h) \\approx 1.7\\ \\text{yr}$ — much faster than the\n",
        "> sediment pool that set $T$. **The horizon is governed by the slowest\n",
        "> process; the step size is governed by the fastest one.**\n",
        ">\n",
        "> Start your sequence at $\\Delta t = 2\\ \\text{yr}$ and halve from there.\n",
        "> If you try something much coarser you may see the simulation diverge\n",
        "> or oscillate wildly; that is worth a sentence, but it is not what the\n",
        "> convergence study is measuring."
      ],
      "id": "b21f50c4-0a71-47bf-81e8-622cb2980df1"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "#### Problem 2.3 (10)\n",
        "\n",
        "Using the step size you justified in Problem 2.2, plot $P(t)$ over the\n",
        "full 300-year simulation.\n",
        "\n",
        "You already have $P(30)$ from Problem 2.2. What does $P$ look like once\n",
        "the simulation has fully run? What is happening physically to the lake\n",
        "between those two points in time, and around when does it happen?"
      ],
      "id": "1bc910ba-b0b9-4fd1-92a6-1a5afae84f36"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "#### Problem 2.4 (7)\n",
        "\n",
        "Suppose a lake manager instead used a simpler one-stock model that\n",
        "ignores the sediment pool entirely (as if $\\kappa = 0$, so there is no\n",
        "recycling at all):\n",
        "\n",
        "$$\\frac{dP}{dt} = L - s_\\text{out}P - hP.$$\n",
        "\n",
        "What is this simplified model’s equilibrium $P$ at\n",
        "$L = 10\\ \\mu\\text{g}/(\\text{L}\\cdot\\text{yr})$, and would the manager\n",
        "have concluded the lake is safely oligotrophic at this loading (recall\n",
        "that sediment release becomes significant once $P$ approaches\n",
        "$m = 25\\ \\mu\\text{g}/\\text{L}$)?\n",
        "\n",
        "Compare this to what you found in Problem 2.3. What does this tell you\n",
        "about the risk of using a simplified model, or a short simulation, to\n",
        "set a “safe” loading level? What would you recommend a lake manager do\n",
        "differently, given what you now know about this system?"
      ],
      "id": "24213480-928b-481d-a49d-20114114edcc"
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## References\n",
        "\n",
        "List any external references consulted, including classmates."
      ],
      "id": "ddc9984d-ba10-446d-ba77-bf4ed919e9d3"
    }
  ],
  "nbformat": 4,
  "nbformat_minor": 5,
  "metadata": {
    "kernel_info": {
      "name": "julia"
    },
    "kernelspec": {
      "name": "julia",
      "display_name": "Julia",
      "language": "julia"
    },
    "language_info": {
      "name": "julia",
      "codemirror_mode": "julia",
      "version": "1.11.5"
    }
  }
}