From 6c39d42f46d531325e95eda45d00325d3a53a018 Mon Sep 17 00:00:00 2001 From: Ethan Pierce Date: Tue, 30 Jul 2024 20:19:10 -0600 Subject: [PATCH 1/5] Add notebook --- lessons/python/yet_another_oop.ipynb | 991 +++++++++++++++++++++++++++ 1 file changed, 991 insertions(+) create mode 100644 lessons/python/yet_another_oop.ipynb diff --git a/lessons/python/yet_another_oop.ipynb b/lessons/python/yet_another_oop.ipynb new file mode 100644 index 0000000..73fd9d3 --- /dev/null +++ b/lessons/python/yet_another_oop.ipynb @@ -0,0 +1,991 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a5a686d8-288b-4fc4-82de-cc4045fbe884", + "metadata": {}, + "source": [ + "# Introduction to Object-Oriented Programming" + ] + }, + { + "cell_type": "code", + "execution_count": 295, + "id": "16b65d76-7454-42ab-81cb-ada3dc221ba1", + "metadata": {}, + "outputs": [], + "source": [ + "# Best practice: import everything at the top\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "id": "e712b64b-a640-4092-bb4c-7a0b1c957c4f", + "metadata": {}, + "source": [ + "## Goals for this lesson\n", + "1. Understand some of the advantages of object-oriented programming\n", + "2. Learn how to use classes to encapsulate data and functions in Python\n", + "3. Implement a class to solve a 1D diffusion problem" + ] + }, + { + "cell_type": "markdown", + "id": "33c44421-ac61-469f-891b-54aaee022439", + "metadata": {}, + "source": [ + "# Why should you use classes? or, POP vs. OOP" + ] + }, + { + "cell_type": "markdown", + "id": "771eb974-1531-47ac-9879-71d357955acf", + "metadata": {}, + "source": [ + "# The world of POP" + ] + }, + { + "cell_type": "markdown", + "id": "aa819cc2-d40b-4e4d-a681-24e7f196cd5b", + "metadata": {}, + "source": [ + "Up until now, we have mostly stayed in the world of \"procedure-oriented programming\" (POP). You write a series of instructions for the computer - \"procedures\" - probably start to organize them into functions, and then call those functions on a bunch of data. This works great when you have a simple problem where you can organize your code like this:" + ] + }, + { + "cell_type": "code", + "execution_count": 372, + "id": "4176e609-72bf-4670-b429-1a9d4476294a", + "metadata": {}, + "outputs": [], + "source": [ + "# Step 1) deal with our data\n", + "baseline_temperature = -10.0\n", + "temperature_amplitude = 25.0\n", + "time_steps = np.arange(3650)\n", + "air_temperature = baseline_temperature + temperature_amplitude * np.sin(2 * np.pi / 365 * time_steps)\n", + "\n", + "# Step 2) make some functions\n", + "def calc_derivative(temperature):\n", + " # does something cool\n", + " pass\n", + "\n", + "def calc_flux(derivative):\n", + " # does something also very cool\n", + " pass\n", + "\n", + "def calc_divergence(flux):\n", + " # maybe we're not entirely sure why this works, but it does\n", + " pass\n", + "\n", + "def plot_results(temperature):\n", + " # hopefully our array has the right shape, otherwise this might break\n", + " pass\n", + "\n", + "# Step 3) run the actual model\n", + "for t in time_steps:\n", + " dT = calc_derivative(air_temperature)\n", + " flux = calc_flux(dT)\n", + " divergence = calc_divergence(flux)\n", + " plot_results(divergence)" + ] + }, + { + "cell_type": "markdown", + "id": "f3adb0f1-d8b7-4603-b665-259e534c2b4c", + "metadata": {}, + "source": [ + "This is all very well and good, and actually quite easy to read and understand when it's a small example like this one. But what would happen if we wanted to run a few models with new sets of parameters? We might end up, for example, with a bunch of arrays with names like surface_temperature_plus_2_degrees, surface_temperature_plus_8_degrees_daily_dt, surface_temperature_plus_8_degrees_monthly_dt, and so on. Then, we might need to change one or two things in our functions for each scenario, so we'll make a few new ones with names like calc_flux_with_geotherm or plot_results_year_by_year. Pretty soon, we're not going to be able to hold all this information in our head, and that's when we'll start to introduce hidden bugs. What happens if we run these functions multiple times for different climate scenarios, but each time we're accidentally modifying the same set of arrays? What happens if we have a bunch of functions that have really similar logic, and we decide to change one line? How many times will we have to make that same change? What would we do if we wanted to run a sensitivity analysis with hundreds of combinations of parameters?" + ] + }, + { + "cell_type": "markdown", + "id": "f2760543-b624-4187-b3df-91a937aed736", + "metadata": {}, + "source": [ + "# The world of OOP" + ] + }, + { + "cell_type": "markdown", + "id": "d16d8a99-9ef2-40fe-994b-36405e5ac5f8", + "metadata": {}, + "source": [ + "A different way we can organize our code is called \"object-oriented programming\" (OOP). The core idea in OOP is to link our *data* with the *functions* that operate on those data. In Python, we'll do this with **classes**. Note that this isn't the only approach - you can totally solve all the problems I mentioned above with clever implementations of functions. But, there are a few really nice benefits to OOP in the context of scientific modeling:\n", + "* We have to organize our code into logical chunks\n", + "* That means we can build big programs by dividing them into small pieces\n", + "* It's really easy for users (that includes you!) to figure out which functions get to modify a chunk of data\n", + "* It's easier to return to code that you wrote a long time ago and understand what's happening\n", + "* We won't have to copy+paste or repeat code very often (if at all)" + ] + }, + { + "cell_type": "markdown", + "id": "b6aabb96-d1d3-4476-bf2d-9d90204942e3", + "metadata": {}, + "source": [ + "# Intro to classes" + ] + }, + { + "cell_type": "markdown", + "id": "08630cbe-cca1-44bf-b758-fcd5b600ec8e", + "metadata": {}, + "source": [ + "Using a class consists of two steps: first we make a blueprint that defines the object, then we make an instance of the object to use it. If you think about it, we actually do the same thing with functions. Here's an example:" + ] + }, + { + "cell_type": "code", + "execution_count": 318, + "id": "fa2dfe7d-1459-4f95-b74d-51a2f1404475", + "metadata": {}, + "outputs": [], + "source": [ + "# \"def\" means we are defining a function\n", + "def my_function(arg_1, arg_2): # the function gets a name, \"my_function\"\n", + " # and it takes two arguments, \"arg_1\" and \"arg_2\"\n", + " result = arg_1 * arg_2 # we can make new variables inside the function\n", + " \n", + " return result # and at the end we should return something" + ] + }, + { + "cell_type": "markdown", + "id": "5d0a67dc-81bb-464e-b1a3-80d70216294e", + "metadata": {}, + "source": [ + "Wait, we just ran the code and it didn't do anything! That's because all we've done here is define the function. To use it, we would have to do something like:" + ] + }, + { + "cell_type": "code", + "execution_count": 319, + "id": "e8160be4-5760-4136-bd19-ce6d9aa1b2e0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "200\n" + ] + } + ], + "source": [ + "# use the function\n", + "answer = my_function(100, 2)\n", + "print(answer)" + ] + }, + { + "cell_type": "markdown", + "id": "c2ec8701-b0fe-402d-9b3a-9808b42c6ea1", + "metadata": {}, + "source": [ + "Let's keep this in mind as we look at classes. First, instead of using \"def\" we'll define a class by calling it ... a class!\n", + "\n", + "##### ***Classes are objects that hold data and the functions that will operate on the data.***" + ] + }, + { + "cell_type": "code", + "execution_count": 311, + "id": "b005bf79-8e9a-422f-8155-35b6d74fc733", + "metadata": {}, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "incomplete input (546207509.py, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m Cell \u001b[0;32mIn[311], line 1\u001b[0;36m\u001b[0m\n\u001b[0;31m class MyModel:\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m incomplete input\n" + ] + } + ], + "source": [ + "class MyModel:" + ] + }, + { + "cell_type": "markdown", + "id": "8f14bae4-f94f-4804-a2df-eb4d26fb61dc", + "metadata": {}, + "source": [ + "This raises an error - similar to the error you would get if you tried to make a function that didn't do anything. Let's keep going. The first thing we need to do is tell Python how to deal with a brand-new instance of this object. We'll do that by defining a \"method.\" \n", + "\n", + "##### ***Methods are functions that belong to a particular class.***" + ] + }, + { + "cell_type": "code", + "execution_count": 326, + "id": "d0b74872-ef9e-42f0-a8a0-b3376012c137", + "metadata": {}, + "outputs": [], + "source": [ + "class MyModel:\n", + "\n", + " def __init__(self, a):\n", + " self.a = a" + ] + }, + { + "cell_type": "markdown", + "id": "f18c6872-8cd4-4c1e-8aba-ef123ee9cb68", + "metadata": {}, + "source": [ + "Let's take a sec and look carefully at what's going on here. First, we have a weird function that's idented a level. This is a method, and we'll treat it exactly like a function, with two exceptions:\n", + "1. Indent methods (along with everything else in a class) one level inside the class definition.\n", + "2. The first argument to a method should be \"self.\"\n", + "\n", + "Note that unlike a lot of things in Python, you can't name \"self\" whatever you want. In this case, it's a reserved keyword that will **always** refer to an instance of the object.\n", + "\n", + "Also, what's with the weird double-underscores on either side of init? and why call it init instead of something like initialize? This is another reserved phrase in Python. Functions that we define ourselves, like my_function, we can name whatever we want. But some functions in Python are built-in - that is, they are given reserved names, and Python will call them using those reserved names in certain situations.\n", + "\n", + "For example, \\_\\_init\\_\\_ gets called when we make a new instance of the class:" + ] + }, + { + "cell_type": "code", + "execution_count": 327, + "id": "0cb8522a-72f5-459e-940c-463b3f0f1c79", + "metadata": {}, + "outputs": [], + "source": [ + "model = MyModel(100)" + ] + }, + { + "cell_type": "markdown", + "id": "09be78da-a682-440e-9f0d-21ee187b63d7", + "metadata": {}, + "source": [ + "Notice that we don't need to specify self. It is implicitly filled in, so we just need to include the arguments after it (in this case, *a*). This will be true every time we call a method. \n", + "\n", + "Now, all of the code we added to the init method was called when we made an instance of MyModel. (Try it out! Add a print statement inside the init method.) In this case, we told Python that *self* - the instance of the model we just made - should have an *attribute* that is equal to the argument a.\n", + "\n", + "##### ***Attributes are pieces of data that belong to an instance of a class.***\n", + "\n", + "We can access attributes using the same \"dot\" syntax that we used to make them:" + ] + }, + { + "cell_type": "code", + "execution_count": 328, + "id": "e30f7525-7dc2-4970-bb56-d3ddd4918fb1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "100" + ] + }, + "execution_count": 328, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.a" + ] + }, + { + "cell_type": "markdown", + "id": "68d55156-37a3-4e54-981c-0e76cf02c8fa", + "metadata": {}, + "source": [ + "To make a new method, we'll just keep adding text to the class definition. We still need to specify *self* as the first argument to the method. We can use class attributes inside methods - in fact, that's one great reason to use classes! And, we can either have them return results, or store those results as new attributes." + ] + }, + { + "cell_type": "code", + "execution_count": 332, + "id": "42d7ac94-966e-4c8b-b1d1-7651ccddff6d", + "metadata": {}, + "outputs": [], + "source": [ + "class MyModel:\n", + "\n", + " def __init__(self, a):\n", + " self.a = a\n", + "\n", + " def add(self, b):\n", + " self.b = self.a + b\n", + "\n", + " def add_and_return(self, b):\n", + " return self.a + b" + ] + }, + { + "cell_type": "code", + "execution_count": 334, + "id": "0220389b-771e-4e52-b0e8-980908b9cc35", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n" + ] + } + ], + "source": [ + "model = MyModel(2)\n", + "model.add(2)\n", + "print(model.b)" + ] + }, + { + "cell_type": "code", + "execution_count": 335, + "id": "ca1e24c7-fb41-48c6-9fe7-4a77a68f5af8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "4\n" + ] + } + ], + "source": [ + "print(model.add_and_return(2))" + ] + }, + { + "cell_type": "markdown", + "id": "426d4cad-d718-4942-9f22-d96973fc4000", + "metadata": {}, + "source": [ + "**Important note:** attributes can be anything you want: strings, numbers, dictionaries, arrays - even other classes!" + ] + }, + { + "cell_type": "markdown", + "id": "e998e99b-d582-4754-bab0-e123eef221cf", + "metadata": {}, + "source": [ + "# Let's build a class!" + ] + }, + { + "cell_type": "markdown", + "id": "27dd142c-cd8b-427f-bb7e-0dbca0144ae6", + "metadata": {}, + "source": [ + "I often find that I don't know what questions I have until I'm actually working with something. So, here's an example problem. It's a much simpler version of something that I'm actually using for research, and I chose to use a class to help me organize it. (More specifically, I made a couple different classes that all work together.)" + ] + }, + { + "cell_type": "markdown", + "id": "41203d29-5dc5-479c-a5d3-7af18e189d0b", + "metadata": {}, + "source": [ + "### Motivation: What sets the temperature profile through an ice sheet?" + ] + }, + { + "cell_type": "markdown", + "id": "9f39a6d4-8d1a-45cb-b0f0-fadd6e77063d", + "metadata": {}, + "source": [ + "We think about half of Greenland's contribution to sea level rise comes from ice discharge. The rate at which ice flows depends on its temperature in two pretty important ways: (1) warmer ice tends to be softer, and thus deforms faster, and (2) warm temperatures at the bed allow ice to slide more rapidly. On longer time scales, this also means that warm-bedded glaciers are much more efficient agents of erosion and sediment transport. We can usually measure the temperature at the surface of the ice sheet, but it's rare that we get to measure the temperature inside the ice. So, it's great opportunity to put together a simple numerical model to give us a prediction to work off of.\n", + "\n", + "Skipping over the full derivation, the temperature (we'll call it $T$) in one dimension can be modeled as:\n", + "\n", + "# $\\rho c\\left(\\frac{dT}{dt} + w\\frac{dT}{dz}\\right) = k\\frac{dT^2}{dz^2} + P.$\n", + "\n", + "The first term here is the time evolution of temperature, where $\\rho$ is the ice density and $c$ is the specific heat. Then, we have vertical advection, which advects cold ice downwards at some vertical velocity $w$. And then on the right-hand side, we have diffusion, modified by thermal conductivity $k$, and any sources or sinks of heat within the ice $P$.\n", + "\n", + "In the simplest possible case, we could ignore vertical advection and any sources or sinks of heat, which would reduce to Fourier's law:\n", + "\n", + "# $\\frac{dT}{dt} = \\kappa\\frac{dT^2}{dz^2},$\n", + "\n", + "where we have also wrapped up $k / (\\rho c)$ into a thermal diffusivity, $\\kappa$. We'll need some boundary conditions, so let's say that the temperature at the surface is equal to -10.0 C, and that the gradient of the temperature, $\\frac{dT}{dz} = 0$ at the bed. We could also consider adding a heat flux from the bed, perhaps from geothermal heating, but that will be a later exercise.\n", + "\n", + "Let's start putting this together in a class. You'll see that this will actually help us organize some of the ideas as we go along." + ] + }, + { + "cell_type": "code", + "execution_count": 379, + "id": "e5e42cab-583e-424e-ac5b-6ce0fe372d6b", + "metadata": {}, + "outputs": [], + "source": [ + "class SimpleGlacier:\n", + " \"\"\"Models the temperature profile with a glacier.\n", + " \n", + " This model is based off of: \n", + " The Physics of Glaciers (Cuffey and Paterson, 2010).\n", + " Lecture notes from Andy Aschwanden (McCarthy school, summer 2012).\n", + "\n", + " Attributes:\n", + " z: an array of z-coordinates\n", + " \"\"\"\n", + "\n", + " def __init__(self, z: np.ndarray, ice_density: float = 917.0):\n", + " \"\"\"Initialize the model with an array of z-coordinates.\"\"\"\n", + " self.z = z\n", + " self.ice_density = ice_density\n", + "\n", + " def run_one_step(self, dt: float) -> np.ndarray:\n", + " \"\"\"Advance the model by one step of size dt.\"\"\"\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "id": "f9b5b52c-de85-4c00-803c-287866cf664d", + "metadata": {}, + "source": [ + "Note that we've added a little bit of extra documentation. One piece of documentation is called type-hinting. By adding a colon after arguments in the function signature, or an arrow after the definition of a function, we can give the user hints as to the input/output types. It's super extra and unnecessary, but I (and many others in CSDMS) like to use it to help us visually see what's going on. You can also use external programs to enforce these types more strictly, but Python will ignore them by default.\n", + "\n", + "More importantly, whenever you see writing inside triple-quotes, it's called a *doc-string*. Basically, it's a string of text that can be automatically read by many different programs, to help people use your model. Try it out:" + ] + }, + { + "cell_type": "code", + "execution_count": 363, + "id": "bc5b6258-ea43-4a08-b1a4-6c8c06ae9f87", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on class SimpleGlacier in module __main__:\n", + "\n", + "class SimpleGlacier(builtins.object)\n", + " | SimpleGlacier(z: numpy.ndarray, ice_density: float = 917.0)\n", + " | \n", + " | Models the temperature profile with a glacier.\n", + " | \n", + " | This model is based off of: \n", + " | The Physics of Glaciers (Cuffey and Paterson, 2010).\n", + " | Lecture notes from Andy Aschwanden (McCarthy school, summer 2012).\n", + " | \n", + " | Attributes:\n", + " | z: an array of z-coordinates\n", + " | \n", + " | Methods defined here:\n", + " | \n", + " | __init__(self, z: numpy.ndarray, ice_density: float = 917.0)\n", + " | Initialize the model with an array of z-coordinates.\n", + " | \n", + " | run_one_step(self, dt: float) -> numpy.ndarray\n", + " | Advance the model by one step of size dt.\n", + " | \n", + " | ----------------------------------------------------------------------\n", + " | Data descriptors defined here:\n", + " | \n", + " | __dict__\n", + " | dictionary for instance variables\n", + " | \n", + " | __weakref__\n", + " | list of weak references to the object\n", + "\n" + ] + } + ], + "source": [ + "help(SimpleGlacier)" + ] + }, + { + "cell_type": "code", + "execution_count": 364, + "id": "56c97ced-a05d-4423-955f-c12e85e24b2d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function run_one_step in module __main__:\n", + "\n", + "run_one_step(self, dt: float) -> numpy.ndarray\n", + " Advance the model by one step of size dt.\n", + "\n" + ] + } + ], + "source": [ + "help(SimpleGlacier.run_one_step)" + ] + }, + { + "cell_type": "markdown", + "id": "30348321-17e4-48a4-b0c1-9e0ace3a2595", + "metadata": {}, + "source": [ + "We also added an attribute with a default value. We could override this:" + ] + }, + { + "cell_type": "code", + "execution_count": 369, + "id": "3e62dcb7-d12f-4f5f-a720-46e17e4e17ca", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10000000000\n" + ] + } + ], + "source": [ + "model = SimpleGlacier(np.arange(10), 10000000000)\n", + "print(model.ice_density)" + ] + }, + { + "cell_type": "markdown", + "id": "b899b575-1d8a-4f74-94d7-2310146034f6", + "metadata": {}, + "source": [ + "But if we don't, we'll get the default value:" + ] + }, + { + "cell_type": "code", + "execution_count": 370, + "id": "4639ce75-4725-4db7-8e86-116a74e80a51", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "917.0\n" + ] + } + ], + "source": [ + "model = SimpleGlacier(np.arange(10))\n", + "print(model.ice_density)" + ] + }, + { + "cell_type": "markdown", + "id": "f0766574-7ee8-4957-aeb1-6196692d2828", + "metadata": {}, + "source": [ + "At this point, you have all the tools you need to extend this class. First, let's add some more parameters: we'll want the thermal conductivity (often 2.1 W m$^{-1}$ K$^{-1}$), the ice density (often 917 kg m$^{-3}$), and the specific heat capacity of ice (2,093 J K$^{-1}$ kg$^{-1}$). Let's also make a decision here: since we don't think anyone will really want to change these values, **don't include them as arguments to \\_\\_init\\_\\_.** Instead, add them as attributes automatically when the class is instantiated.\n", + "\n", + "### Question: if you wanted to, could you still change these parameter values for a particular instance of the class?\n", + "(Try it!)\n", + "\n", + "### Next, write a method to calculate the thermal diffusivity. \n", + "(It's up to you if you want to store that value as an attribute or return it directly.)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20dc1ec1-3e83-45d3-89ee-2c4a9ace143a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "2ef7596d-bb6f-4484-9c85-d435282d6d32", + "metadata": {}, + "source": [ + "Now, let's write the rest of the model. This will be mostly self-directed." + ] + }, + { + "cell_type": "markdown", + "id": "f95f8fcd-f0da-4cce-a2c2-8e5dcb968d9f", + "metadata": {}, + "source": [ + "![rest-of-the-owl](draw-the-owl.jpg)" + ] + }, + { + "cell_type": "markdown", + "id": "4d4b08d0-7027-4fae-909e-4fe8d43c2113", + "metadata": {}, + "source": [ + "Just kidding - here's a template, but feel free to draw your own owl :)" + ] + }, + { + "cell_type": "code", + "execution_count": 541, + "id": "0fe24f77-be64-4235-88b6-b7f766d72be7", + "metadata": {}, + "outputs": [], + "source": [ + "class SimpleGlacier:\n", + " \"\"\"Models the temperature profile with a glacier.\n", + " \n", + " This model is based off of: \n", + " The Physics of Glaciers (Cuffey and Paterson, 2010).\n", + " Lecture notes from Andy Aschwanden (McCarthy school, summer 2012).\n", + "\n", + " Attributes:\n", + " z: an array of z-coordinates\n", + " temperature: an array representing the temperature profile with depth\n", + " \"\"\"\n", + "\n", + " def __init__(self, z: np.ndarray, initial_temperature: np.ndarray):\n", + " \"\"\"Initialize the model with arrays of z-coordinates and initial temperature profile.\"\"\"\n", + " self.z = z\n", + " self.temperature = initial_temperature\n", + "\n", + " # We probably want to calculate dz --> try using np.gradient\n", + "\n", + " # We'll need attributes for rho, c, and k\n", + " # You could also store info about boundary conditions at this point, if you want\n", + " \n", + " # Maybe we should go ahead and calculate diffusivity right away?\n", + " \n", + " # Let's keep track of the elapsed time\n", + "\n", + " def calc_diffusivity(self):\n", + " \"\"\"From above, kappa = k / (rho * c).\"\"\"\n", + " pass\n", + "\n", + " def calc_heat_flux(self):\n", + " \"\"\"The heat flux is -kappa * dT / dz.\"\"\"\n", + " \n", + " # How should we calculate the difference in temperature with depth? (hint: see dz, above)\n", + "\n", + " # Are dT and dz the same size? Are they the same size as z?\n", + "\n", + " # Don't forget to apply boundary conditions! The heat flux at the bed should be zero, for now.\n", + " \n", + " pass\n", + "\n", + " def calc_divergence(self):\n", + " \"\"\"In 1D, divergence is just the derivative. yay!\"\"\"\n", + " pass\n", + " \n", + " def run_one_step(self, dt: float) -> np.ndarray:\n", + " \"\"\"Advance the model by one step of size dt.\"\"\"\n", + "\n", + " # updated temperature = current temperature + the divergence * dt\n", + "\n", + " # Don't forget to apply boundary conditions! The temperature at the surface is equal to a fixed value.\n", + "\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "id": "3c4c3074-58b2-4997-8991-42f3e95b8eaa", + "metadata": {}, + "source": [ + "### Test case: " + ] + }, + { + "cell_type": "code", + "execution_count": 539, + "id": "d74164bf-7cbe-47cf-a825-9bc249684fff", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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tByNfsvsnnvuUb9+/bR9+3YdPXpU5eXl9nb06NEmbW7EiBFatmyZVq1apaeeekpbtmzR4MGD7aBSWlqqiIgIRUdH+zwvISFBpaWlds3pAPV98fHxds3Z5Ofn22uOLMtScnJyE14ZAABoSRo9Q7R792797//+ry677LJA9OPjl7/8pf1zSkqK+vXrp65du+qdd97Rrbfees7nGWPkcrnsx9//+Vw1Z5o5c6amT59uP/Z6vYQiAADaqEbPEKWmpurLL78MRC8N6ty5s7p27ardu3dLkhITE1VTU6Py8nKfurKyMiUkJNg1hw4dqneuw4cP2zVn43a7FRUV5bMBAIC2ya8Zok8//dT+OScnRzNmzFBpaal69+6t8PBwn9o+ffo0bYffc+TIEe3fv1+dO3eWJPXt21fh4eEqKirSmDFjJEklJSXavn27nnzySUlSWlqaPB6PNm/erOuuu06StGnTJnk8Hr6GBAAASPIzEF111VVyuVw+i6jvvPNO++fTxxq7qLqystJntmnPnj0qLi5WTEyMYmJiNGfOHN12223q3Lmz9u7dq1mzZikuLk633HKLJMmyLE2YMEEzZsxQbGysYmJilJeXp969e9ufOuvVq5eGDx+uiRMnatGiRZKkSZMmKTMzk0+YAQAASX4Goj179gRk8I8++kiDBg2yH59eszNu3DgtXLhQn332mZYuXaqKigp17txZgwYN0vLlyxUZGWk/Z/78+QoLC9OYMWNUVVWlm266SUuWLFFoaKhds2zZMk2bNs3+NFpWVtZ5//YRAABwFpc587PzDVizZo3S09MVFuabpU6dOqX169c36u8QtSZer1eWZcnj8bCeCACAJvSzZ9dqZ4lXS++8Tjde3qlJz+3v63ejF1UPGjTorB+v93g8PrM9AAAArUWjA9G5Pq5+5MgRdejQoUmaAgAAaE5+/x2i03/3x+Vyafz48XK73fax2tpaffrpp3xqCwAAtEp+ByLLsiT9e4YoMjJS7du3t49FRESof//+mjhxYtN3CAAAEGB+B6LFixdLkrp166a8vDzeHgMAAG1Go7+6Y/bs2ZL+/degd+3aJZfLpcsvv/ys3xcGAADQGjR6UbXX61V2drYuueQSDRgwQDfeeKMuueQS3X777fJ4PIHoEQAAIKAaHYjuuusubdq0SW+//bYqKirk8Xj09ttv66OPPmINEQAA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cDw+ZQYAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQALcCRI0cUHx+vvXv3+uyvqanRjBkzlJeXp5qamiYd8+c//7mefvrpJj0n0FoRiADI5XKddxs/fnywWwyYgQMHKjc3N9htKD8/X6NGjVK3bt189i9fvlzXXHONrr/+er3yyit+n6+0tFQ5OTn60Y9+JLfbreTkZI0aNUr/+Mc/7JpHHnlEc+fOldfrbarLAFqtsGA3ACD4SkpK7J+XL1+uRx55RLt27bL3tW/fPhht/WA1NTWKiIhoNWNWVVXppZde0sqVK+sdq6urU3h4uGpra1VXV+fX+fbu3avrr79eHTt21JNPPqk+ffro5MmTevfddzVlyhR98cUXkqQ+ffqoW7duWrZsme69994f1DvQZhgA+J7Fixcby7Lq7a+rqzNPPPGE6d69u2nXrp3p06eP+ctf/uJTM2DAADN16lRz3333mY4dO5r4+HizaNEiU1lZacaPH28uvvhi86Mf/cisXLnS5zlTpkwxU6ZMMZZlmZiYGPPQQw+Zuro6v8c+fY7777/fxMbGmhtvvNEYY8zf//53c/3119vnHTlypPnyyy/t540bN85I8tn27NljunbtaubPn+9zbVdeeaWZPXt2g2P6c5/O9MYbb5i4uLizHjtx4oS57777TG5urjlx4sR5z3PaiBEjzCWXXGIqKyvrHSsvL/d5PGfOHPPTn/7Ur/MCbRlvmQHwy8MPP6zFixdr4cKF2rFjh+6//37dfvvtWr16tU/dyy+/rLi4OG3evFk5OTm699579Ytf/ELp6enatm2bhg0bpuzsbH333Xc+zwkLC9OmTZv0+9//XvPnz9eLL77YqLFPn+Of//ynFi1aJEk6fvy4pk+fri1btugf//iHQkJCdMstt9gzLc8++6zS0tI0ceJElZSUqKSkRMnJyX7fk7ON6e99+r41a9aoX79+Zz3mdrv1zDPPaP78+XK73Q32dPToURUWFmrKlCnq0KFDveMdO3b0eXzddddp8+bNqq6ubvDcQJsW7EQGoGU52wxRZWWladeunVm/fr3P/gkTJphf/epX9uMBAwaYG264wX586tQp06FDB5OdnW3vKykpMZLMhg0b7Of06tXLZ0boN7/5jenVq5ffYw8YMMBcddVVDV5bWVmZkWQ+++wzn57vu+8+nzp/Z4jOHNPf+3Smm2++2dx5550N9u+PTZs2GUnmzTff9Kv+k08+MZLM3r17m2R8oLViDRGABu3cuVMnTpzQ0KFDffbX1NTo6quv9tnXp08f++fQ0FDFxsaqd+/e9r6EhARJUllZmb2vf//+crlc9uO0tDQ99dRTqq2t9Xvss82w/Otf/9Jvf/tbbdy4Ud9++609M7Rv3z6lpKT4ff3ncuaYjblP31dVVaV27dpdcD+SZIyRJJ/7eT6n14d9f8YOcCICEYAGnQ4S77zzji655BKfY2e+jRMeHu7z2OVy+ew7/ULt7wJhf8c+29tDo0aNUnJysl544QUlJSWprq5OKSkpDX58PSQkxA4Wp508ebJe3ZljNuY+fV9cXJzKy8vP25O/evToIZfLpc8//1yjR49usP7o0aOSpE6dOjXJ+EBrRSAC0KArrrhCbrdb+/bt04ABA5r8/Bs3bqz3uEePHgoNDf3BYx85ckSff/65Fi1apJ/+9KeSpHXr1tWri4iIUG1trc++Tp06+Xzyzuv1as+ePQ2O+UN7vfrqq/Xqq6/6XX8+MTExGjZsmJ577jlNmzatXmirqKjwWUe0fft2denSRXFxcU0yPtBaEYgANCgyMlJ5eXm6//77VVdXpxtuuEFer1fr16/XxRdfrHHjxl3Q+ffv36/p06fr7rvv1rZt2/SHP/xBTz311AWNHR0drdjYWP3pT39S586dtW/fPj344IP16rp166ZNmzZp7969uvjiixUTE6PBgwdryZIlGjVqlKKjo/Xb3/5WoaGhAbtPw4YN08yZM1VeXq7o6OhG3Lmz++Mf/6j09HRdd911evTRR9WnTx+dOnVKRUVFWrhwoT7//HO7du3atcrIyLjgMYHWjkAEwC+PPfaY4uPjlZ+fr6+++kodO3bUNddco1mzZl3wue+44w5VVVXpuuuuU2hoqHJycjRp0qQLGjskJEQFBQWaNm2aUlJS1LNnT/3+97/XwIEDfery8vI0btw4XXHFFaqqqtKePXs0c+ZMffXVV8rMzJRlWXrsscf8miH6ob327t1b/fr10//8z//o7rvv9muc8+nevbu2bdumuXPnasaMGSopKVGnTp3Ut29fLVy40K47ceKEVqxYoXffffeCxwRaO5c5841yAGhGAwcO1FVXXaVnnnkm2K0E1cqVK5WXl6ft27crJKR5/iLKc889p7feekvvvfdes4wHtGTMEAFAC/Czn/1Mu3fv1sGDBxv1t5AuRHh4uP7whz80y1hAS0cgAoAW4r777mvW8b7/tiTgdLxlBgAAHI+v7gAAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI73/wHDgjrWrsPGJgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# The Greenland ice sheet is 3,053 m thick at the summit!\n", + "z = np.arange(3053)\n", + "\n", + "# Let's set the temperature to 0.0 C everywhere, except the surface\n", + "T0 = np.full_like(z, -5.0)\n", + "T0[0] = -10.0\n", + "\n", + "# Tip: maybe you wnat to include this plotting function into your class?\n", + "plt.plot(T0, z)\n", + "plt.xlabel('Temperature ($^\\circ$ C)')\n", + "plt.ylabel('Depth (m)')\n", + "plt.gca().invert_yaxis() # This forces matplotlib to invert the y-axis\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "4f86e05f-a0d6-4fcf-8db8-c650d7960a1b", + "metadata": {}, + "source": [ + "Now, let's test out your model. I want to run it using the exact code below. As you do, think about the following questions:\n", + "1) Does it pass? Try to move things around until the code runs without any errors.\n", + "2) Plot the output. Does it match what you might expect?\n", + "3) What should the steady-state profile look like? What parameters can we change to converge faster/slower?" + ] + }, + { + "cell_type": "code", + "execution_count": 528, + "id": "d216e3d2-986e-4d3f-82c1-e6ed2fbfbc43", + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'SimpleGlacier' object has no attribute 'time_elapsed'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[528], line 7\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m365\u001b[39m): \n\u001b[1;32m 6\u001b[0m model\u001b[38;5;241m.\u001b[39mrun_one_step(dt)\n\u001b[0;32m----> 7\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtime_elapsed\u001b[49m\u001b[38;5;250m \u001b[39m\u001b[38;5;241m/\u001b[39m\u001b[38;5;250m \u001b[39m\u001b[38;5;241m31556926\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m years.\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 9\u001b[0m model\u001b[38;5;241m.\u001b[39mplot()\n", + "\u001b[0;31mAttributeError\u001b[0m: 'SimpleGlacier' object has no attribute 'time_elapsed'" + ] + } + ], + "source": [ + "model = SimpleGlacier(z, T0)\n", + "\n", + "dt = 60 * 60 * 24\n", + "\n", + "for i in range(365): \n", + " model.run_one_step(dt)\n", + " print(f'{model.time_elapsed / 31556926} years.')\n", + "\n", + "model.plot()" + ] + }, + { + "cell_type": "markdown", + "id": "7ae3c5ca-a9eb-4481-961f-1cc0d07911a5", + "metadata": {}, + "source": [ + "Once you've done that, we could think about how to add a better boundary condition at the bed. A typical geothermal heat flux in Greenland is $0.04$ W m$^{-2}$ - but don't forget to also divide by $(\\rho * c)$ to keep the units intact! Maybe we should also let the user pass their own geothermal heat flux to our model. At this point, I bet you can figure out how to do that." + ] + }, + { + "cell_type": "code", + "execution_count": 538, + "id": "2ebbb16c-f568-4358-992f-4bfe38817afc", + "metadata": {}, + "outputs": [], + "source": [ + "# Plot results here!" + ] + }, + { + "cell_type": "markdown", + "id": "2d0e9161-1824-4be5-8f17-a3ea322e01f6", + "metadata": {}, + "source": [ + "## Bonus exercises" + ] + }, + { + "cell_type": "markdown", + "id": "6823da3c-aa7c-415f-aa76-0dbb925b135c", + "metadata": {}, + "source": [ + "### 1) Time-dependent boundary conditions\n", + "Classes are powerful frameworks when you need to change or extend your code. Take a look at the time series of air temperature provided at the start of this notebook. How would you build this into the SimpleGlacier class?" + ] + }, + { + "cell_type": "markdown", + "id": "1630e180-b1e1-4851-aa21-d6ac3367ef2a", + "metadata": {}, + "source": [ + "### 2) Plotting in 2D\n", + "We could also visualize this problem using a heat map, with time as the x-axis, depth as the y-axis, and temperature as the color map. For this, we'll need to modify our class to save a 2D array. We probably don't want to save every single time step, so let's also add an **if** statement to the run_one_step method to only save on certain intervals. Then, we can use the matplotlib function plt.imshow to visualize our 2D array, like so:" + ] + }, + { + "cell_type": "code", + "execution_count": 542, + "id": "7de68364-01b1-4c34-8c43-4392411f5a4a", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAeMAAAGdCAYAAAAhXxuJAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/TGe4hAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAlpElEQVR4nO3df3RU9Z3/8dedwUwAk1hgE0FCiFtcUqIVErolgK3VZg8qR/vdFaoWLIJLNhGIaSlEbEUUptjKplUTjV+LUgFzrHrEXVqbbY/8KHXFGK1Hu9Jv8WsihGahfhMEmUjmfv9QssYbMJObzOczmefjnPtHLvPJ550x5j3v9+fe+3Fc13UFAACMCZgOAACAZEcyBgDAMJIxAACGkYwBADCMZAwAgGEkYwAADCMZAwBgGMkYAADDhsR7wmg0qoMHDyotLU2O48R7egCAD67r6ujRoxozZowCgYGr506cOKGOjg7f3yclJUWpqan9ENHAinsyPnjwoLKzs+M9LQCgHzU3N2vs2LED8r1PnDihMUPP1nvq9P29zj33XL399tvWJ+S4J+O0tDRJ0usr5iktlBLv6U9rxyU/Mh2Cx4R7ZpsOwWPoiOGmQ/DYV7LFdAgejftMR+D12n/+X9MheFQ03mw6BI/Qw0+ZDsHjYHuG6RC6HD/Wrpuuyu36Wz4QOjo69J469Vjq+RrmYzX1uKK68dB+dXR0kIw/7VRrOi2UovRUe5LxsOHppkPwOPusuP/n+UzDUs4yHYLHsLPt+2+XOsx0BF5npZxtOgSP4cGg6RA8Us8euCTTV8Oi9v2Ox2OZcZgCGub4+B1JoJ0X7PtrDwCAJGeIo4CPpO+4iXNdEskYAGAl56yAHKfvbWongTYlJBkDAKwUCDoKBPpe3QaiiVMZc58xAACGURkDAKzknOXI8VEZOwlUGZOMAQBWCgyhTQ0AAOKEyhgAYCXa1AAAGBYIOgoEfbSpOxMnGdOmBgDAMCpjAICVnKAjx0dl7GiQV8bV1dXKzc1VamqqCgoKtGvXrv6OCwCQ5E61qf0ciSLmZFxXV6fy8nKtWrVKjY2NmjlzpmbNmqWmpqaBiA8AgEEv5mS8YcMGLVy4UIsWLVJeXp6qqqqUnZ2tmpqagYgPAJCknIDj+0gUMa0Zd3R0qKGhQStXrux2vri4WHv27OlxTCQSUSQS6fq6vb29D2ECAJKNEwzICfrYKCKB9lCM6ac8fPiwOjs7lZWV1e18VlaWDh061OOYcDisjIyMriM7O7vv0QIAkgZrxp/h05tKu6572o2mKysr1dbW1nU0Nzf3ZUoAAAatmNrUo0aNUjAY9FTBra2tnmr5lFAopFAo1PcIAQBJyXGS5wlcMVXGKSkpKigoUH19fbfz9fX1Kioq6tfAAADJzQn6a1U7QdM/Qe/F/NCPiooKzZs3T4WFhZo2bZpqa2vV1NSkkpKSgYgPAIBBL+ZkPHfuXB05ckRr1qxRS0uL8vPztX37duXk5AxEfACAJOX7CVxu4rSp+/Q4zNLSUpWWlvZ3LAAAdHECATkBH7c2+Rgbb4kTKQAAgxQbRQAArOT3KVqD9glcAADEi+/9jBNozZg2NQAAhlEZAwCsRJsaAADDHMfn1dRO4jR/ScYAACslU2WcOB8bAAAYpKiMAQBW8n01dQJtFEEyBgBYiTY1AACIG2OV8Y/T71JoaLqp6T0y9rumQ/C4KC3VdAge5119uekQPI7edpnpEDwyf/Ks6RA8VnzuBdMheBz4Tp3pEDxO3naD6RA8tn1xs+kQunScOBq3uZLp2dS0qQEAVqJNDQAA4obKGABgpWSqjEnGAAArJVMypk0NAIBhVMYAACt9VBn7uZo6cSpjkjEAwEpOwN8TuJxOkjEAAL6wZgwAAOKGyhgAYCWewAUAgGG0qQEAQNxQGQMArJRMlTHJGABgpWRaM06cSAEAGKSojAEAVqJNDQCAYbSpAQBA3FAZAwDs5DgfHX7GJwiSMQDASo7jc82YZAwAgD+sGQMAgLihMgYAWIlbmwAAMIw2NQAAiBsqYwCAlZyAv1azk0DlJskYAGClZFozTqDPDQAADLzq6mrl5uYqNTVVBQUF2rVr1xlfv3nzZn3xi1/UsGHDNHr0aC1YsEBHjhyJaU6SMQDAToGA/yNGdXV1Ki8v16pVq9TY2KiZM2dq1qxZampq6vH1u3fv1vz587Vw4UK98cYbevLJJ7V3714tWrQoth815kgBAIgDx3F8H7HasGGDFi5cqEWLFikvL09VVVXKzs5WTU1Nj69/8cUXNX78eC1dulS5ubmaMWOGFi9erJdffjmmeUnGAIBBrb29vdsRiUR6fF1HR4caGhpUXFzc7XxxcbH27NnT45iioiK9++672r59u1zX1V/+8hf94he/0JVXXhlTjCRjAICVTt1n7OeQpOzsbGVkZHQd4XC4x/kOHz6szs5OZWVldTuflZWlQ4cO9TimqKhImzdv1ty5c5WSkqJzzz1X55xzju67776YflaupgYAWKm/rqZubm5Wenp61/lQKHTmcZ9qb7uue9qW95tvvqmlS5fqBz/4gf7hH/5BLS0tWr58uUpKSvTII4/0OlaSMQDATk7fLsLqNl5Senp6t2R8OqNGjVIwGPRUwa2trZ5q+ZRwOKzp06dr+fLlkqSLLrpIw4cP18yZM3X33Xdr9OjRvQqVNjUAAJJSUlJUUFCg+vr6bufr6+tVVFTU45jjx48r8KkPDMFgUNJHFXVvURkDAOzks02tPoytqKjQvHnzVFhYqGnTpqm2tlZNTU0qKSmRJFVWVurAgQPatGmTJGn27Nm6+eabVVNT09WmLi8v15e+9CWNGTOm1/MaS8bfbf++0jtSTE3vcfKS+aZD8DhQ+HPTIXj8v86e77Uzqe3efzYdgkdgzgzTIXi8Nty+z94rzrvIdAge5Sv+3XQIHj/c/i+mQ+hy9MMObYrTXI4TkOPjmZZ9GTt37lwdOXJEa9asUUtLi/Lz87V9+3bl5ORIklpaWrrdc/ztb39bR48e1f3336/vfOc7Ouecc/S1r31N69evj2le+/7vBADAoNLSUpWWlvb4b48++qjn3JIlS7RkyRJfc5KMAQB2Cjh9ajV3G58gSMYAACuxnzEAAIgbKmMAgJWSaQtFkjEAwE6O0/Xgjj6PTxC0qQEAMIzKGABgJdrUAACYFvD5bOoEupqaZAwAsJLjOKfdLam34xNF4nxsAABgkKIyBgDYqZ+2UEwEJGMAgJWS6QKuxPnYAADAIBVTMg6Hw5o6darS0tKUmZmpa665Rm+99dZAxQYASGZOwP+RIGKKdMeOHSorK9OLL76o+vp6nTx5UsXFxTp27NhAxQcASFandm3ycySImNaMf/WrX3X7euPGjcrMzFRDQ4MuueSSfg0MAIBk4esCrra2NknSiBEjTvuaSCSiSCTS9XV7e7ufKQEAScJxAnJ8tJr9jI23Pkfquq4qKio0Y8YM5efnn/Z14XBYGRkZXUd2dnZfpwQAJJMkalP3ORnfcsst+sMf/qCtW7ee8XWVlZVqa2vrOpqbm/s6JQAAg1Kf2tRLlizRtm3btHPnTo0dO/aMrw2FQgqFQn0KDgCQvJxAQI6Ph374GRtvMSVj13W1ZMkSPfPMM3rhhReUm5s7UHEBAJKd4/jbkziBnk0dUzIuKyvTli1b9OyzzyotLU2HDh2SJGVkZGjo0KEDEiAAIEkFHJ+7NiVOMo7pp6ypqVFbW5u++tWvavTo0V1HXV3dQMUHAMCgF3ObGgCAuKBNDQCAWcl0AVfiRAoAwCBFZQwAsJPfzR4S6AlcJGMAgJ0cn0/RSqA148T52AAAwCBFZQwAsFIybRRBMgYA2MnvZg+D9aEfAACg/1EZAwDsxNXUAAAYxhO4AAAwLBDwuVEElfFn+ut/NenDlLNMTe/R+NUvmQ7B4+/uutR0CB7Rf/2p6RA8nnguYjoEj2V/N9J0CB5jby0zHYLHk9trTYfg8V/DLjQdgsdPcx8wHUKXyAftkjaZDmPQoTIGANiJNWMAAAzj1iYAABAvVMYAADs5js82deJUxiRjAICdkujWJtrUAAAYRmUMALAT9xkDAGAYbWoAABAvVMYAADvx0A8AAAxzfK4Zk4wBAPCJNWMAABAvVMYAADuxZgwAgGG0qQEAQLxQGQMA7MQTuAAAMMt1HLk+Ws1+xsZb4nxsAABgkKIyBgDYif2MAQAwLIlubUqcSAEAGKSojAEAVkqmC7hIxgAAOyVRm5pkDACwE0/gAgAA8UJlDACwE0/gAgDArGS6gCtxPjYAABAH1dXVys3NVWpqqgoKCrRr164zvj4SiWjVqlXKyclRKBTS3/7t3+pnP/tZTHNSGQMA7GTgauq6ujqVl5erurpa06dP10MPPaRZs2bpzTff1Lhx43ocM2fOHP3lL3/RI488os9//vNqbW3VyZMnY5qXZAwAsJLrBOT6SMZ9GbthwwYtXLhQixYtkiRVVVXp+eefV01NjcLhsOf1v/rVr7Rjxw7t379fI0aMkCSNHz8+5nlpUwMABrX29vZuRyQS6fF1HR0damhoUHFxcbfzxcXF2rNnT49jtm3bpsLCQt1zzz0677zzdMEFF+i73/2uPvjgg5hipDIGANipn+4zzs7O7nb6jjvu0OrVqz0vP3z4sDo7O5WVldXtfFZWlg4dOtTjFPv379fu3buVmpqqZ555RocPH1Zpaan++te/xrRuTDIGAFjJlc829cfN3+bmZqWnp3edD4VCZxznfOoDgOu6nnOnRKNROY6jzZs3KyMjQ9JHre5/+qd/0gMPPKChQ4f2KlaSMQDATv1UGaenp3dLxqczatQoBYNBTxXc2trqqZZPGT16tM4777yuRCxJeXl5cl1X7777riZMmNCrUFkzBgBAUkpKigoKClRfX9/tfH19vYqKinocM336dB08eFDvv/9+17l9+/YpEAho7NixvZ7bWGU8prhI6cNSTU3vcduT75gOweNf9r1nOgSPoUMyPvtFcfan1/abDsFj+Noq0yF4/Pg/LzAdgseQSVeZDsHjiqVfMR2Cxwdz/sN0CF0iH3TGbzLH8XlrU+xVdUVFhebNm6fCwkJNmzZNtbW1ampqUklJiSSpsrJSBw4c0KZNmyRJ119/ve666y4tWLBAd955pw4fPqzly5frpptu6nWLWqJNDQCwlIkncM2dO1dHjhzRmjVr1NLSovz8fG3fvl05OTmSpJaWFjU1NXW9/uyzz1Z9fb2WLFmiwsJCjRw5UnPmzNHdd98d07wkYwAAPqG0tFSlpaU9/tujjz7qOTdx4kRPaztWJGMAgJ3YzxgAALNcOXLlo03tY2y8Jc7HBgAABikqYwCAlUw8m9oUkjEAwE5JtGacOJECADBIURkDAKxk4j5jU0jGAAArsWYMAIBp/bRRRCJInI8NAAAMUlTGAAA7+WxTJ9LV1CRjAICVeAJXL4XDYTmOo/Ly8n4KBwCA5NPnynjv3r2qra3VRRdd1J/xAAAgKbmupu5TpO+//75uuOEGPfzww/rc5z7X3zEBACA5+p8rqvt0mP4Beq9PybisrExXXnmlLr/88s98bSQSUXt7e7cDAAD8j5jb1E888YReeeUV7d27t1evD4fDuvPOO2MODACQ3FwF5Pq4tMnP2HiLKdLm5mYtW7ZMjz/+uFJTU3s1prKyUm1tbV1Hc3NznwIFACSXU4/D9HMkipgq44aGBrW2tqqgoKDrXGdnp3bu3Kn7779fkUhEwWCw25hQKKRQKNQ/0QIAMAjFlIwvu+wyvf76693OLViwQBMnTtSKFSs8iRgAgL5KpqupY0rGaWlpys/P73Zu+PDhGjlypOc8AAB+JNNDP3gCFwDASlTGMXjhhRf6IQwAAJIXlTEAwEp+r4getFdTAwAQL8m0Zpw4DXUAAAYpKmMAgJW4gAsAAMNoUwMAgLihMgYAWMmVzzZ1AtWbJGMAgJVoUwMAgLihMgYAWOmjh374uZo6cSpjkjEAwErJ1KY2loybp8zR2Wlppqb3eCjv/5gOwePdfSNMh+Dxb2+MMx2Cxx2v/y/TIXg8uPv3pkPwKJmxz3QIHhltTaZD8PjgvirTIXhUbvuu6RC6tJ/o0E/jNFcyPQ6TNWMAAAyjTQ0AsJLrOnJdH5Wxj7HxRjIGAFgq4PNe4cRp/iZOpAAADFJUxgAAK3E1NQAAhiVTMqZNDQCAYVTGAAArJVNlTDIGAFgpmZIxbWoAAAyjMgYAWImHfgAAYFgytalJxgAAKyVTMmbNGAAAw6iMAQBWSqbKmGQMALCSK58XcCVQMqZNDQCAYVTGAAArReUo6qO69TM23kjGAAArJdOaMW1qAAAMozIGAFiJJ3ABAGCYK3+tZrf/QhlwtKkBADCMyhgAYCXa1AAAGJZMV1OTjAEAVkqmypg1YwAADKMyBgBYyZUU9Tk+UZCMAQBWok0NAADihmQMALDSqaup/Rx9UV1drdzcXKWmpqqgoEC7du3q1bjf/e53GjJkiC6++OKY5yQZAwCsdKpN7eeIVV1dncrLy7Vq1So1NjZq5syZmjVrlpqams44rq2tTfPnz9dll13Wp5+VZAwAwMc2bNighQsXatGiRcrLy1NVVZWys7NVU1NzxnGLFy/W9ddfr2nTpvVpXpIxAMBK/dWmbm9v73ZEIpEe5+vo6FBDQ4OKi4u7nS8uLtaePXtOG+fGjRv15z//WXfccUeff1aSMQDASlHX/yFJ2dnZysjI6DrC4XCP8x0+fFidnZ3Kysrqdj4rK0uHDh3qccyf/vQnrVy5Ups3b9aQIX2/QYlbmwAAg1pzc7PS09O7vg6FQmd8veN0X2t2XddzTpI6Ozt1/fXX684779QFF1zgK0ZjyThUtVypKWeZmt5j2egzrweYkDr9KdMheCy6p8h0CB4X3n6d6RA8/uOEffc3BtxO0yF4HPnc502H4LH+qZGmQ/D416lfNh1Cl45jH0j633GZq7+eTZ2ent4tGZ/OqFGjFAwGPVVwa2urp1qWpKNHj+rll19WY2OjbrnlFklSNBqV67oaMmSIfv3rX+trX/tar2KlMgYAWCneD/1ISUlRQUGB6uvr9Y1vfKPrfH19va6++mrP69PT0/X66693O1ddXa3f/va3+sUvfqHc3Nxez00yBgBYyXU/OvyMj1VFRYXmzZunwsJCTZs2TbW1tWpqalJJSYkkqbKyUgcOHNCmTZsUCASUn5/fbXxmZqZSU1M95z8LyRgAgI/NnTtXR44c0Zo1a9TS0qL8/Hxt375dOTk5kqSWlpbPvOe4L0jGAAArReUo6mPNuK9jS0tLVVpa2uO/Pfroo2ccu3r1aq1evTrmOUnGAAArsVEEAACIGypjAICVTFzAZQrJGABgpf66zzgR0KYGAMAwKmMAgJU++Xzpvo5PFCRjAICdfF5NLa6mBgAAvUVlDACwEldTAwBgmKkncJkQc5v6wIED+ta3vqWRI0dq2LBhuvjii9XQ0DAQsQEAktipytjPkShiqozfe+89TZ8+XZdeeql++ctfKjMzU3/+8591zjnnDFB4AAAMfjEl4/Xr1ys7O1sbN27sOjd+/Pj+jgkAAJ5NfTrbtm1TYWGhrr32WmVmZmry5Ml6+OGHzzgmEomovb292wEAwGc5dZ+xnyNRxJSM9+/fr5qaGk2YMEHPP/+8SkpKtHTpUm3atOm0Y8LhsDIyMrqO7Oxs30EDADCYxJSMo9GopkyZonXr1mny5MlavHixbr75ZtXU1Jx2TGVlpdra2rqO5uZm30EDAAY/LuA6jdGjR+sLX/hCt3N5eXl66qmnTjsmFAopFAr1LToAQNJio4jTmD59ut56661u5/bt26ecnJx+DQoAgGQSU2V86623qqioSOvWrdOcOXP00ksvqba2VrW1tQMVHwAgSUXlc6OIfotk4MVUGU+dOlXPPPOMtm7dqvz8fN11112qqqrSDTfcMFDxAQCSFGvGZ3DVVVfpqquuGohYAABISjybGgBgJTaKAADAsKjrKOrjKVp+xsYbyRgAYKVkqoxj3rUJAAD0LypjAICVkqkyJhkDAKzk+tzsIZGSMW1qAAAMozIGAFgpmfYzJhkDAKyUTGvGtKkBADCMyhgAYKWozwu4/IyNN2PJ+OStP9SHaWmmpvdYffc/mw7B46eTt5gOwSP3wSrTIXjsvOQm0yF47C+1b/OUtqJRpkPwONY51HQIHlet+rLpEDw2/tt/mQ6hywcftktaHJe5aFMDAIC4oU0NALBSMlXGJGMAgJVYMwYAwLBkqoxZMwYAwDAqYwCAlaLRjw4/4xMFyRgAYCXa1AAAIG6ojAEAVkqmyphkDACwUlQ+b23qt0gGHm1qAAAMozIGAFjJdV25PnrNfsbGG8kYAGClZFozpk0NAIBhVMYAACu5Ph/64SbQFVwkYwCAlZKpTU0yBgBYKZl2bWLNGAAAw6iMAQBWok0NAIBhbtSV66PX7GdsvNGmBgDAMCpjAICVkukCLpIxAMBKybRmTJsaAADDqIwBAFaKRl1FffSa/YyNN5IxAMBKtKkBAEDcUBkDAKyUTJUxyRgAYKWo6yrqI6P6GRtvJGMAgJXcqL9tEBNpC0XWjAEAMIxkDACwkitXruvjUN/a1NXV1crNzVVqaqoKCgq0a9eu07726aef1te//nX9zd/8jdLT0zVt2jQ9//zzMc9JMgYAWMmNSlEfR1/a1HV1dSovL9eqVavU2NiomTNnatasWWpqaurx9Tt37tTXv/51bd++XQ0NDbr00ks1e/ZsNTY2xjQvyRgAgI9t2LBBCxcu1KJFi5SXl6eqqiplZ2erpqamx9dXVVXpe9/7nqZOnaoJEyZo3bp1mjBhgp577rmY5iUZAwCs5KtF/fEhSe3t7d2OSCTS43wdHR1qaGhQcXFxt/PFxcXas2dPr2KORqM6evSoRowYEdPPSjIGAFjp1K5Nfg5Jys7OVkZGRtcRDod7nO/w4cPq7OxUVlZWt/NZWVk6dOhQr2K+9957dezYMc2ZMyemn9XYrU3u3bfKPcueO6uaVz1tOgSPNfWrTIfg8defvG06BI8103tuH5l0w4zRpkPwOP/NatMheHR+LtN0CB7jb5tuOgSPoSUXmQ6hy7Fop+kQYtbc3Kz09PSur0Oh0Blf7zhOt69d1/Wc68nWrVu1evVqPfvss8rMjO13255sCADAJ7hRV66PzR5OjU1PT++WjE9n1KhRCgaDniq4tbXVUy1/Wl1dnRYuXKgnn3xSl19+ecyx0qYGAFjp1OMw/RyxSElJUUFBgerr67udr6+vV1FR0WnHbd26Vd/+9re1ZcsWXXnllX35UamMAQA4paKiQvPmzVNhYaGmTZum2tpaNTU1qaSkRJJUWVmpAwcOaNOmTZI+SsTz58/XT37yE335y1/uqqqHDh2qjIyMXs9LMgYAWMnEfsZz587VkSNHtGbNGrW0tCg/P1/bt29XTk6OJKmlpaXbPccPPfSQTp48qbKyMpWVlXWdv/HGG/Xoo4/2el6SMQDASp+8Pamv4/uitLRUpaWlPf7bpxPsCy+80Kc5Po1kDACwEhtFAACAuKEyBgBYif2MAQAwzNSasQm0qQEAMIzKGABgJRO3NplCMgYAWKkvT9H69PhEQZsaAADDqIwBAFZyXZ8bRSRQaRxTZXzy5Endfvvtys3N1dChQ3X++edrzZo1ikYT6M5qAEBCcD++tamvRyIl45gq4/Xr1+vBBx/UY489pkmTJunll1/WggULlJGRoWXLlg1UjAAADGoxJePf//73uvrqq7u2iBo/fry2bt2ql19+eUCCAwAkr/7azzgRxNSmnjFjhn7zm99o3759kqTXXntNu3fv1hVXXHHaMZFIRO3t7d0OAAA+y6lk7OdIFDFVxitWrFBbW5smTpyoYDCozs5OrV27Vtddd91px4TDYd15552+AwUAJJeo+9HhZ3yiiKkyrqur0+OPP64tW7bolVde0WOPPaYf//jHeuyxx047prKyUm1tbV1Hc3Oz76ABABhMYqqMly9frpUrV+qb3/ymJOnCCy/UO++8o3A4rBtvvLHHMaFQSKFQyH+kAICkkkxrxjEl4+PHjysQ6F5MB4NBbm0CAPS7ZNooIqZkPHv2bK1du1bjxo3TpEmT1NjYqA0bNuimm24aqPgAABj0YkrG9913n77//e+rtLRUra2tGjNmjBYvXqwf/OAHAxUfACBJRaP+NntIpKZtTMk4LS1NVVVVqqqqGqBwAAD4SDK1qdkoAgAAw9goAgBgJa6mBgDAsGRKxrSpAQAwjMoYAGClqD7aCtHP+ERBMgYAWCmZ2tQkYwCAlbi1CQAAxA2VMQDASm7U9fUELtrUAAD4lExrxrSpAQAwzFhl/C/vV2jIWcNNTe8x+4/27bk8dfJU0yF4fK95qekQPLZ+74TpEDz2tNr3ibzuw1LTIXi8+tox0yF4XPvv602H4PH4gv8wHUKXjhNHpR9OiMtcyXQBF21qAICV3GhUro+tl/yMjTfa1AAAGEZlDACwUtTn1dR+xsYbyRgAYKVkWjOmTQ0AgGFUxgAAKyXTfcYkYwCAlUjGAAAYFlVUUbfvtydFxa1NAACgl6iMAQBWcqP+Ws0+iuq4IxkDAKyUTGvGtKkBADCMyhgAYKVkeugHyRgAYKVoNKqoj80e/IyNN9rUAAAYRmUMALBSMl3ARTIGAFjJdaNyfdyf5GdsvNGmBgDAMCpjAICVaFMDAGCaz2QskjEAAP5EXZ8bRbBmDAAAeovKGABgJdaMAQAwzHWjcn08RYtbmwAAQK9RGQMArESbGgAAw3gCFwAAiBsqYwCAlaJRKeqj1ZxAOyiSjAEAdnKjPq+mTqBsTJsaAADDqIwBAFbiamoAAAxLpqupScYAACslU2XMmjEAAIbFvTJ23Y8+qXSePB7vqc/oxPF20yF4tB+z6z2SpA8jR02H4HH0/YjpEDyOH7Pv96njQ8d0CB6RD46ZDsHjWGen6RA8Ok7Y8//dqb8Bp/6WD6STHUd9XRHdedK+36/Tcdx4vKOf8O677yo7OzueUwIA+llzc7PGjh07IN/7xIkTys3N1aFDh3x/r3PPPVdvv/22UlNT+yGygRP3ZByNRnXw4EGlpaXJcfr+Sb29vV3Z2dlqbm5Wenp6P0Y4uPA+9Q7vU+/wPvXOYH6fXNfV0aNHNWbMGAUCA7fSeeLECXV0dPj+PikpKdYnYslAmzoQCPTrp6n09PRB98s+EHifeof3qXd4n3pnsL5PGRkZAz5HampqQiTR/sIFXAAAGEYyBgDAsIRNxqFQSHfccYdCoZDpUKzG+9Q7vE+9w/vUO7xPiFXcL+ACAADdJWxlDADAYEEyBgDAMJIxAACGkYwBADAsYZNxdXW1cnNzlZqaqoKCAu3atct0SFYJh8OaOnWq0tLSlJmZqWuuuUZvvfWW6bCsFg6H5TiOysvLTYdinQMHDuhb3/qWRo4cqWHDhuniiy9WQ0OD6bCscvLkSd1+++3Kzc3V0KFDdf7552vNmjWK+ni2MpJHQibjuro6lZeXa9WqVWpsbNTMmTM1a9YsNTU1mQ7NGjt27FBZWZlefPFF1dfX6+TJkyouLtaxY4nz4PR42rt3r2pra3XRRReZDsU67733nqZPn66zzjpLv/zlL/Xmm2/q3nvv1TnnnGM6NKusX79eDz74oO6//3798Y9/1D333KMf/ehHuu+++0yHhgSQkLc2/f3f/72mTJmimpqarnN5eXm65pprFA6HDUZmr//+7/9WZmamduzYoUsuucR0OFZ5//33NWXKFFVXV+vuu+/WxRdfrKqqKtNhWWPlypX63e9+R/fpM1x11VXKysrSI4880nXuH//xHzVs2DD9/Oc/NxgZEkHCVcYdHR1qaGhQcXFxt/PFxcXas2ePoajs19bWJkkaMWKE4UjsU1ZWpiuvvFKXX3656VCstG3bNhUWFuraa69VZmamJk+erIcffth0WNaZMWOGfvOb32jfvn2SpNdee027d+/WFVdcYTgyJIK4bxTh1+HDh9XZ2amsrKxu57Oysvplu63ByHVdVVRUaMaMGcrPzzcdjlWeeOIJvfLKK9q7d6/pUKy1f/9+1dTUqKKiQrfddpteeuklLV26VKFQSPPnzzcdnjVWrFihtrY2TZw4UcFgUJ2dnVq7dq2uu+4606EhASRcMj7l09svuq7ra0vGweyWW27RH/7wB+3evdt0KFZpbm7WsmXL9Otf/zqpdoeJVTQaVWFhodatWydJmjx5st544w3V1NSQjD+hrq5Ojz/+uLZs2aJJkybp1VdfVXl5ucaMGaMbb7zRdHiwXMIl41GjRikYDHqq4NbWVk+1DGnJkiXatm2bdu7cOWAbgSeqhoYGtba2qqCgoOtcZ2endu7cqfvvv1+RSETBYNBghHYYPXq0vvCFL3Q7l5eXp6eeespQRHZavny5Vq5cqW9+85uSpAsvvFDvvPOOwuEwyRifKeHWjFNSUlRQUKD6+vpu5+vr61VUVGQoKvu4rqtbbrlFTz/9tH77298qNzfXdEjWueyyy/T666/r1Vdf7ToKCwt1ww036NVXXyURf2z69Ome2+L27dunnJwcQxHZ6fjx4woEuv9JDQaD3NqEXkm4yliSKioqNG/ePBUWFmratGmqra1VU1OTSkpKTIdmjbKyMm3ZskXPPvus0tLSujoJGRkZGjp0qOHo7JCWluZZQx8+fLhGjhzJ2von3HrrrSoqKtK6des0Z84cvfTSS6qtrVVtba3p0Kwye/ZsrV27VuPGjdOkSZPU2NioDRs26KabbjIdGhKBm6AeeOABNycnx01JSXGnTJni7tixw3RIVpHU47Fx40bToVntK1/5irts2TLTYVjnueeec/Pz891QKOROnDjRra2tNR2Sddrb291ly5a548aNc1NTU93zzz/fXbVqlRuJREyHhgSQkPcZAwAwmCTcmjEAAIMNyRgAAMNIxgAAGEYyBgDAMJIxAACGkYwBADCMZAwAgGEkYwAADCMZAwBgGMkYAADDSMYAABhGMgYAwLD/D4Kgw1Q67QYTAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Replace test_array with your results\n", + "test_array = np.random.random((10, 10))\n", + "\n", + "plt.imshow(test_array, cmap = 'coolwarm')\n", + "plt.colorbar()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "de364600-bada-48bc-88b1-f6db9d6f0c2c", + "metadata": {}, + "source": [ + "### 3) Vertical advection\n", + "This gets a little more spicy than you might expect. Remember from above, we still have that pesky little $w\\frac{dT}{dz}$ hanging out in our PDE. By now, we do know how to calculate $\\frac{dT}{dz}$. In fact, maybe we should make that little calculation it's own method? It's a good time to check if you have any repeated code :) \n", + "\n", + "If we're truly in the middle of an ice sheet, we might assume the vertical velocity ($w$ in our equations here) scales with depth and the mass balance at the ice surface:\n", + "\n", + "# $w(z) = -\\frac{b(H - z)}{H}$,\n", + "\n", + "where $b$ is the mass balance (accumulation - ablation) and $H$ is the ice thickness. Let's use a baseline value for $b$ of around a centimeter per year, but you should play with this number and see how it impacts your temperature profiles.\n", + "\n", + "The trick here is that the size of our time steps might be too large when we add advection. One way to check is to use a CFL condition: a metric of stability. For diffusive equations, like this one, we should be okay if we're in the range:\n", + "\n", + "# $\\frac{\\kappa\\Delta t}{\\Delta z}\\leq 0.5$,\n", + "\n", + "but there might be some complications as the advective component of the system grows. You know what would be sweet? What if we wrote a method that calculates the stable time step - we could even let the user know if they accidentally try to run the model with a time step that's too large!" + ] + }, + { + "cell_type": "markdown", + "id": "42c8b497-97be-4690-b8c6-15d11e842819", + "metadata": {}, + "source": [ + "### 4) Inheritance\n", + "Imagine you want to make this class more general - after all, it's just a 1D diffusion model! We could take the universal pieces out of this class and make a new class:" + ] + }, + { + "cell_type": "code", + "execution_count": 373, + "id": "d54d9620-8be3-44d5-846f-cf58b616030b", + "metadata": {}, + "outputs": [], + "source": [ + "class DiffusionModel1D:\n", + "\n", + " def __init__(self):\n", + " pass\n", + "\n", + " def run_one_step(self):\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "id": "cbc47af2-e9e8-4e9f-b4e7-5018d279eb25", + "metadata": {}, + "source": [ + "Then, the SimpleGlacier class could **inherit** from this *parent* class, becoming a *child* class of DiffusionModel1D.\n", + "##### Child classes inherit all the methods and attributes of their parents, except where specified." + ] + }, + { + "cell_type": "code", + "execution_count": 548, + "id": "9bdc456b-4425-48ef-8b5f-aa9a42a33abe", + "metadata": {}, + "outputs": [], + "source": [ + "# Example of a child class\n", + "class DiffusionChild(DiffusionModel1D):\n", + "\n", + " def __init__(self):\n", + " pass\n", + "\n", + " def no_parents_allowed(self):\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": 547, + "id": "df9ab5b5-a885-4219-b49f-32cbf7dfee25", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Help on function run_one_step in module __main__:\n", + "\n", + "run_one_step(self)\n", + "\n" + ] + } + ], + "source": [ + "help(DiffusionChild.run_one_step)" + ] + }, + { + "cell_type": "markdown", + "id": "0129517b-feca-4918-a979-de727bef9f56", + "metadata": {}, + "source": [ + "But, parent classes do not get any of the information defined by their children:" + ] + }, + { + "cell_type": "code", + "execution_count": 549, + "id": "1474651c-a28b-4c5a-92ed-271be7b98b9a", + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "type object 'DiffusionModel1D' has no attribute 'no_parents_allowed'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[549], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m help(\u001b[43mDiffusionModel1D\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mno_parents_allowed\u001b[49m)\n", + "\u001b[0;31mAttributeError\u001b[0m: type object 'DiffusionModel1D' has no attribute 'no_parents_allowed'" + ] + } + ], + "source": [ + "help(DiffusionModel1D.no_parents_allowed)" + ] + }, + { + "cell_type": "markdown", + "id": "c2530246-6011-4d2b-926f-a9f11a237940", + "metadata": {}, + "source": [ + "Let's play around with this idea. First, split SimpleGlacier into a parent class and a child class. Then, try to make a new diffusion model that inherits from the same parent class, but adds a new method for plotting data." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 0c21701a527b087690b23e0f85598a264c08f575 Mon Sep 17 00:00:00 2001 From: Ethan Pierce Date: Tue, 30 Jul 2024 20:21:10 -0600 Subject: [PATCH 2/5] Add media --- lessons/python/media/draw-the-owl.jpg | Bin 0 -> 23085 bytes lessons/python/yet_another_oop.ipynb | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 lessons/python/media/draw-the-owl.jpg diff --git a/lessons/python/media/draw-the-owl.jpg b/lessons/python/media/draw-the-owl.jpg new file mode 100644 index 0000000000000000000000000000000000000000..695208b1e63fe11793b087616f341537517d07fa GIT binary patch literal 23085 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%0D1NasslkJ2yX;PFp~@ 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 literal 0 HcmV?d00001 diff --git a/lessons/python/yet_another_oop.ipynb b/lessons/python/yet_another_oop.ipynb index 73fd9d3..0e028ca 100644 --- a/lessons/python/yet_another_oop.ipynb +++ b/lessons/python/yet_another_oop.ipynb @@ -610,7 +610,7 @@ "id": "f95f8fcd-f0da-4cce-a2c2-8e5dcb968d9f", "metadata": {}, "source": [ - "![rest-of-the-owl](draw-the-owl.jpg)" + "![rest-of-the-owl](./media/draw-the-owl.jpg)" ] }, { From 622c7e112944da51335be75056b2b2a5fa5ecf29 Mon Sep 17 00:00:00 2001 From: Ethan Pierce Date: Thu, 1 Aug 2024 08:42:54 -0600 Subject: [PATCH 3/5] Add answers to yet_another_oop notebook --- lessons/python/yet_another_oop.ipynb | 191 ++++++++++++++++++++++----- 1 file changed, 159 insertions(+), 32 deletions(-) diff --git a/lessons/python/yet_another_oop.ipynb b/lessons/python/yet_another_oop.ipynb index 0e028ca..2193ed1 100644 --- a/lessons/python/yet_another_oop.ipynb +++ b/lessons/python/yet_another_oop.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": 295, + "execution_count": 2, "id": "16b65d76-7454-42ab-81cb-ada3dc221ba1", "metadata": {}, "outputs": [], @@ -623,7 +623,7 @@ }, { "cell_type": "code", - "execution_count": 541, + "execution_count": 52, "id": "0fe24f77-be64-4235-88b6-b7f766d72be7", "metadata": {}, "outputs": [], @@ -646,41 +646,65 @@ " self.temperature = initial_temperature\n", "\n", " # We probably want to calculate dz --> try using np.gradient\n", - "\n", + " self.dz = np.gradient(self.z)\n", + " # Note: I didn't realize this when I originally wrote the class, but we won't need dz\n", + " # Want to know why? Check out the documentation for np.gradient -> https://numpy.org/doc/stable/reference/generated/numpy.gradient.html\n", + " \n", " # We'll need attributes for rho, c, and k\n", " # You could also store info about boundary conditions at this point, if you want\n", + " self.rho = 917\n", + " self.c = 2093\n", + " self.k = 2.1\n", + "\n", + " # Let's store boundary conditions too\n", + " self.surface_temperature = -10.0\n", + " self.basal_heat_flux = 0.0\n", " \n", " # Maybe we should go ahead and calculate diffusivity right away?\n", + " self.kappa = self.calc_diffusivity()\n", " \n", " # Let's keep track of the elapsed time\n", + " self.time_elapsed = 0.0\n", "\n", - " def calc_diffusivity(self):\n", + " def calc_diffusivity(self) -> float:\n", " \"\"\"From above, kappa = k / (rho * c).\"\"\"\n", - " pass\n", + " return self.k / (self.rho * self.c)\n", "\n", - " def calc_heat_flux(self):\n", + " def calc_heat_flux(self) -> np.ndarray:\n", " \"\"\"The heat flux is -kappa * dT / dz.\"\"\"\n", " \n", " # How should we calculate the difference in temperature with depth? (hint: see dz, above)\n", + " temperature_gradient = np.gradient(self.temperature, self.z)\n", "\n", " # Are dT and dz the same size? Are they the same size as z?\n", + " assert temperature_gradient.shape == self.dz.shape == self.z.shape\n", "\n", " # Don't forget to apply boundary conditions! The heat flux at the bed should be zero, for now.\n", - " \n", - " pass\n", + " temperature_gradient[-1] = self.basal_heat_flux\n", "\n", - " def calc_divergence(self):\n", + " return -self.kappa * temperature_gradient\n", + " \n", + " def calc_divergence(self) -> np.ndarray:\n", " \"\"\"In 1D, divergence is just the derivative. yay!\"\"\"\n", - " pass\n", + " heat_flux = self.calc_heat_flux()\n", + " \n", + " flux_divergence = np.gradient(heat_flux, self.z)\n", + " \n", + " return flux_divergence\n", " \n", - " def run_one_step(self, dt: float) -> np.ndarray:\n", + " def run_one_step(self, dt: float):\n", " \"\"\"Advance the model by one step of size dt.\"\"\"\n", + " flux_divergence = self.calc_divergence()\n", "\n", - " # updated temperature = current temperature + the divergence * dt\n", + " # updated temperature = current temperature - the divergence * dt\n", + " updated_temperature = self.temperature - flux_divergence * dt\n", "\n", " # Don't forget to apply boundary conditions! The temperature at the surface is equal to a fixed value.\n", + " updated_temperature[0] = self.surface_temperature\n", "\n", - " pass" + " self.temperature = updated_temperature\n", + "\n", + " self.time_elapsed += dt" ] }, { @@ -693,7 +717,7 @@ }, { "cell_type": "code", - "execution_count": 539, + "execution_count": 44, "id": "d74164bf-7cbe-47cf-a825-9bc249684fff", "metadata": {}, "outputs": [ @@ -737,32 +761,73 @@ }, { "cell_type": "code", - "execution_count": 528, + "execution_count": 49, "id": "d216e3d2-986e-4d3f-82c1-e6ed2fbfbc43", "metadata": {}, "outputs": [ { - "ename": "AttributeError", - "evalue": "'SimpleGlacier' object has no attribute 'time_elapsed'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[528], line 7\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;241m365\u001b[39m): \n\u001b[1;32m 6\u001b[0m model\u001b[38;5;241m.\u001b[39mrun_one_step(dt)\n\u001b[0;32m----> 7\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtime_elapsed\u001b[49m\u001b[38;5;250m \u001b[39m\u001b[38;5;241m/\u001b[39m\u001b[38;5;250m \u001b[39m\u001b[38;5;241m31556926\u001b[39m\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m years.\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 9\u001b[0m model\u001b[38;5;241m.\u001b[39mplot()\n", - "\u001b[0;31mAttributeError\u001b[0m: 'SimpleGlacier' object has no attribute 'time_elapsed'" + "name": "stdout", + "output_type": "stream", + "text": [ + "0.05475818525543331 years.\n", + "54.81294344068874 years.\n", + "109.57112869612205 years.\n", + "164.32931395155535 years.\n", + "219.08749920698867 years.\n", + "273.84568446242196 years.\n", + "328.6038697178553 years.\n", + "383.3620549732886 years.\n", + "438.1202402287219 years.\n", + "492.87842548415523 years.\n", + "547.6366107395885 years.\n", + "602.3947959950218 years.\n", + "657.1529812504551 years.\n", + "711.9111665058884 years.\n", + "766.6693517613218 years.\n", + "821.4275370167551 years.\n", + "876.1857222721884 years.\n", + "930.9439075276217 years.\n", + "985.7020927830549 years.\n", + "1040.4602780384882 years.\n", + "1095.2184632939216 years.\n", + "1149.9766485493549 years.\n", + "1204.7348338047882 years.\n", + "1259.4930190602215 years.\n", + "1314.2512043156548 years.\n", + "1369.0093895710881 years.\n", + "1423.7675748265215 years.\n", + "1478.5257600819548 years.\n", + "1533.283945337388 years.\n", + "1588.0421305928214 years.\n" ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ "model = SimpleGlacier(z, T0)\n", "\n", - "dt = 60 * 60 * 24\n", + "dt = 60 * 60 * 24 * 20\n", "\n", - "for i in range(365): \n", + "for i in range(30000): \n", " model.run_one_step(dt)\n", - " print(f'{model.time_elapsed / 31556926} years.')\n", "\n", - "model.plot()" + " if i % 1000 == 0:\n", + " print(f'{model.time_elapsed / 31556926} years.')\n", + "\n", + "plt.plot(model.temperature, model.z)\n", + "plt.xlabel('Temperature ($^\\circ$ C)')\n", + "plt.ylabel('Depth (m)')\n", + "plt.gca().invert_yaxis() # This forces matplotlib to invert the y-axis\n", + "plt.show()" ] }, { @@ -770,17 +835,79 @@ "id": "7ae3c5ca-a9eb-4481-961f-1cc0d07911a5", "metadata": {}, "source": [ - "Once you've done that, we could think about how to add a better boundary condition at the bed. A typical geothermal heat flux in Greenland is $0.04$ W m$^{-2}$ - but don't forget to also divide by $(\\rho * c)$ to keep the units intact! Maybe we should also let the user pass their own geothermal heat flux to our model. At this point, I bet you can figure out how to do that." + "Once you've done that, we could think about how to add a better boundary condition at the bed. Let's add a geothermal heat flux of $0.01$ W m$^{-2}$. Maybe we should also let the user pass their own geothermal heat flux to our model. At this point, I bet you can figure out how to do that." ] }, { "cell_type": "code", - "execution_count": 538, - "id": "2ebbb16c-f568-4358-992f-4bfe38817afc", + "execution_count": 54, + "id": "42bbf2f2-3791-4e8d-b4dc-066d3d50a5d1", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0.05475818525543331 years.\n", + "54.81294344068874 years.\n", + "109.57112869612205 years.\n", + "164.32931395155535 years.\n", + "219.08749920698867 years.\n", + "273.84568446242196 years.\n", + "328.6038697178553 years.\n", + "383.3620549732886 years.\n", + "438.1202402287219 years.\n", + "492.87842548415523 years.\n", + "547.6366107395885 years.\n", + "602.3947959950218 years.\n", + "657.1529812504551 years.\n", + "711.9111665058884 years.\n", + "766.6693517613218 years.\n", + "821.4275370167551 years.\n", + "876.1857222721884 years.\n", + "930.9439075276217 years.\n", + "985.7020927830549 years.\n", + "1040.4602780384882 years.\n", + "1095.2184632939216 years.\n", + "1149.9766485493549 years.\n", + "1204.7348338047882 years.\n", + "1259.4930190602215 years.\n", + "1314.2512043156548 years.\n", + "1369.0093895710881 years.\n", + "1423.7675748265215 years.\n", + "1478.5257600819548 years.\n", + "1533.283945337388 years.\n", + "1588.0421305928214 years.\n" + ] + }, + { + "data": { + "image/png": "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1GW0KovFIsyfP1/QarWCSqUSRo4cKRw/flzqslrcwYMHhbi4OEGtVgvu7u5Cjx49hNdff10oLy+XurRWl56e3i63Bzh69KgwfPhwQaPRCEqlUoiIiBCefPJJITs7W+rSWtzq1asb/I5tbvThGiUiIiKiRvCqNyIiIqJGMCgRERERNYJBiYiIiKgRDEpEREREjWBQIiIiImoEgxIRERFRIxiUiIiIiBrBoERERETUCAYlIiIiokYwKBERERE1gkGJiMgJFBUVQavVIiMjw+64xWLB/PnzsWDBAlgslhb9zAcffBDvvvtui74nUXvDoEREkMlk131MmzZN6hJbzbBhwzB37lypy8DSpUsxYcIERERE2B3fuHEjbr/9dtx5551Yt25dk99Pr9djzpw56NKlC5RKJcLCwjBhwgT8/PPPYpvXXnsNixcvhslkaqluELU7LlIXQETSy8vLE3/euHEjXnvtNaSlpYnHPDw8pCjrplksFri5ubWZz6yoqMBnn32GLVu21DtntVrh6uqKmpoaWK3WJr1fRkYG7rzzTvj6+uKtt95Cnz59UFVVha1bt+Lpp5/G6dOnAQB9+vRBREQE1q9fj6eeeuqmaidq9wQiojpWr14tqNXqesetVquwbNkyITIyUnB3dxf69OkjfPXVV3Zthg4dKsyePVt49tlnBV9fX0Gr1QqrVq0SysrKhGnTpgne3t5Cly5dhC1btti95umnnxaefvppQa1WCxqNRnjllVcEq9Xa5M+ufY/nnntO8Pf3F4YMGSIIgiD897//Fe68807xfe+55x7h3Llz4uumTp0qALB7pKenC+Hh4cLy5cvt+ta3b1/h9ddfv+FnNuXX6Vpff/21EBAQ0OC5yspK4dlnnxXmzp0rVFZWXvd9ao0bN04IDQ0VysrK6p0zGAx2zxctWiTcddddTXpfoo6IU29E1CSvvvoqVq9ejZUrV+LEiRN47rnn8Oijj2LXrl127T7//HMEBARg//79mDNnDp566ik89NBDSEhIwKFDhzBmzBgkJibi8uXLdq9xcXHBvn378P7772P58uX49NNPm/XZte/x22+/YdWqVQCA8vJyzJs3DwcOHMDPP/8MuVyO++67TxyZ+cc//oH4+HjMmDEDeXl5yMvLQ1hYWJN/TRr6zKb+OtW1e/duDBgwoMFzSqUS7733HpYvXw6lUnnDmoqLi5GUlISnn34aXl5e9c77+vraPR84cCD2798Ps9l8w/cm6pCkTmpE5FwaGlEqKysT3N3dheTkZLvj06dPFx555BHx+dChQ4XBgweLz6urqwUvLy8hMTFRPJaXlycAEPbu3Su+pmfPnnYjSC+++KLQs2fPJn/20KFDhX79+t2wbwUFBQIA4dixY3Y1P/vss3btmjqidO1nNvXX6Vr33nuv8Kc//emG9TfFvn37BADCN99806T2R44cEQAIGRkZLfL5RO0N1ygR0Q2dPHkSlZWVGDVqlN1xi8WC/v372x3r06eP+LNCoYC/vz9iYmLEYzqdDgBQUFAgHhs0aBBkMpn4PD4+Hu+88w5qamqa/NkNjcicP38ef/7zn5GSkoJLly6JI0mZmZmIjo5ucv8bc+1nNufXqa6Kigq4u7vfcj0AIAgCANj9el5P7fqzuiN8RHQVgxIR3VBtwPjxxx8RGhpqd+7a6SBXV1e75zKZzO5Y7Rd4UxcmN/WzG5pmmjBhAsLCwvDJJ58gJCQEVqsV0dHRN7zMXi6Xi4GjVlVVVb12135mc36d6goICIDBYLhuTU0VFRUFmUyGU6dOYdKkSTdsX1xcDAAIDAxskc8nam8YlIjohnr16gWlUonMzEwMHTq0xd8/JSWl3vOoqCgoFIqb/uyioiKcOnUKq1atwl133QUA2LNnT712bm5uqKmpsTsWGBhodyWgyWRCenr6DT/zZmvt378//v3vfze5/fVoNBqMGTMGH374IZ555pl6Ya6kpMRundLx48fRqVMnBAQEtMjnE7U3DEpEdEMqlQoLFizAc889B6vVisGDB8NkMiE5ORne3t6YOnXqLb1/VlYW5s2bhyeeeAKHDh3CBx98gHfeeeeWPtvPzw/+/v74+OOPERwcjMzMTLz00kv12kVERGDfvn3IyMiAt7c3NBoNRowYgTVr1mDChAnw8/PDn//8ZygUilb7dRozZgwWLlwIg8EAPz+/ZvzKNeyf//wnEhISMHDgQLzxxhvo06cPqqursX37dqxcuRKnTp0S2/76668YPXr0LX8mUXvFoERETfLmm29Cq9Vi6dKluHDhAnx9fXH77bfj5ZdfvuX3fuyxx1BRUYGBAwdCoVBgzpw5mDlz5i19tlwux4YNG/DMM88gOjoaPXr0wPvvv49hw4bZtVuwYAGmTp2KXr16oaKiAunp6Vi4cCEuXLiA8ePHQ61W480332zSiNLN1hoTE4MBAwbgP//5D5544okmfc71REZG4tChQ1i8eDHmz5+PvLw8BAYGIjY2FitXrhTbVVZWYtOmTdi6destfyZReyUTrp2IJyJyoGHDhqFfv3547733pC5FUlu2bMGCBQtw/PhxyOWO2bnlww8/xHfffYdt27Y55POI2iKOKBEROYE//OEPOHv2LHJycpq1l9OtcHV1xQcffOCQzyJqqxiUiIicxLPPPuvQz6s7vUlEDePUGxEREVEjeAsTIiIiokYwKBERERE1gkGJiIiIqBEMSkRERESNYFAiIiIiagSDEhEREVEjGJSIiIiIGsGgRERERNQIBiUiIiKiRjAoERERETXi/wE3vODiQm76UAAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "# Plot results here!" + "model = SimpleGlacier(z, T0)\n", + "model.basal_heat_flux = 0.01\n", + "\n", + "dt = 60 * 60 * 24 * 20\n", + "\n", + "for i in range(30000): \n", + " model.run_one_step(dt)\n", + "\n", + " if i % 1000 == 0:\n", + " print(f'{model.time_elapsed / 31556926} years.')\n", + "\n", + "plt.plot(model.temperature, model.z)\n", + "plt.xlabel('Temperature ($^\\circ$ C)')\n", + "plt.ylabel('Depth (m)')\n", + "plt.gca().invert_yaxis() # This forces matplotlib to invert the y-axis\n", + "plt.show()" ] }, { From 501aa153642748f50b02c4c82a5563101b2c458a Mon Sep 17 00:00:00 2001 From: Ethan Pierce Date: Thu, 1 Aug 2024 09:00:19 -0600 Subject: [PATCH 4/5] Hide answers in OOP lesson --- lessons/python/yet_another_oop.ipynb | 467 ++++++++++----------------- 1 file changed, 167 insertions(+), 300 deletions(-) diff --git a/lessons/python/yet_another_oop.ipynb b/lessons/python/yet_another_oop.ipynb index 2193ed1..bbe9484 100644 --- a/lessons/python/yet_another_oop.ipynb +++ b/lessons/python/yet_another_oop.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "id": "16b65d76-7454-42ab-81cb-ada3dc221ba1", "metadata": {}, "outputs": [], @@ -57,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": 372, + "execution_count": 2, "id": "4176e609-72bf-4670-b429-1a9d4476294a", "metadata": {}, "outputs": [], @@ -140,7 +140,7 @@ }, { "cell_type": "code", - "execution_count": 318, + "execution_count": 3, "id": "fa2dfe7d-1459-4f95-b74d-51a2f1404475", "metadata": {}, "outputs": [], @@ -163,7 +163,7 @@ }, { "cell_type": "code", - "execution_count": 319, + "execution_count": 4, "id": "e8160be4-5760-4136-bd19-ce6d9aa1b2e0", "metadata": {}, "outputs": [ @@ -193,7 +193,7 @@ }, { "cell_type": "code", - "execution_count": 311, + "execution_count": 5, "id": "b005bf79-8e9a-422f-8155-35b6d74fc733", "metadata": {}, "outputs": [ @@ -202,7 +202,7 @@ "evalue": "incomplete input (546207509.py, line 1)", "output_type": "error", "traceback": [ - "\u001b[0;36m Cell \u001b[0;32mIn[311], line 1\u001b[0;36m\u001b[0m\n\u001b[0;31m class MyModel:\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m incomplete input\n" + "\u001b[0;36m Cell \u001b[0;32mIn[5], line 1\u001b[0;36m\u001b[0m\n\u001b[0;31m class MyModel:\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m incomplete input\n" ] } ], @@ -222,7 +222,7 @@ }, { "cell_type": "code", - "execution_count": 326, + "execution_count": null, "id": "d0b74872-ef9e-42f0-a8a0-b3376012c137", "metadata": {}, "outputs": [], @@ -251,7 +251,7 @@ }, { "cell_type": "code", - "execution_count": 327, + "execution_count": null, "id": "0cb8522a-72f5-459e-940c-463b3f0f1c79", "metadata": {}, "outputs": [], @@ -275,21 +275,10 @@ }, { "cell_type": "code", - "execution_count": 328, + "execution_count": null, "id": "e30f7525-7dc2-4970-bb56-d3ddd4918fb1", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "100" - ] - }, - "execution_count": 328, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "model.a" ] @@ -304,7 +293,7 @@ }, { "cell_type": "code", - "execution_count": 332, + "execution_count": null, "id": "42d7ac94-966e-4c8b-b1d1-7651ccddff6d", "metadata": {}, "outputs": [], @@ -323,18 +312,10 @@ }, { "cell_type": "code", - "execution_count": 334, + "execution_count": null, "id": "0220389b-771e-4e52-b0e8-980908b9cc35", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4\n" - ] - } - ], + "outputs": [], "source": [ "model = MyModel(2)\n", "model.add(2)\n", @@ -343,18 +324,10 @@ }, { "cell_type": "code", - "execution_count": 335, + "execution_count": null, "id": "ca1e24c7-fb41-48c6-9fe7-4a77a68f5af8", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4\n" - ] - } - ], + "outputs": [], "source": [ "print(model.add_and_return(2))" ] @@ -415,7 +388,7 @@ }, { "cell_type": "code", - "execution_count": 379, + "execution_count": null, "id": "e5e42cab-583e-424e-ac5b-6ce0fe372d6b", "metadata": {}, "outputs": [], @@ -453,70 +426,20 @@ }, { "cell_type": "code", - "execution_count": 363, + "execution_count": null, "id": "bc5b6258-ea43-4a08-b1a4-6c8c06ae9f87", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Help on class SimpleGlacier in module __main__:\n", - "\n", - "class SimpleGlacier(builtins.object)\n", - " | SimpleGlacier(z: numpy.ndarray, ice_density: float = 917.0)\n", - " | \n", - " | Models the temperature profile with a glacier.\n", - " | \n", - " | This model is based off of: \n", - " | The Physics of Glaciers (Cuffey and Paterson, 2010).\n", - " | Lecture notes from Andy Aschwanden (McCarthy school, summer 2012).\n", - " | \n", - " | Attributes:\n", - " | z: an array of z-coordinates\n", - " | \n", - " | Methods defined here:\n", - " | \n", - " | __init__(self, z: numpy.ndarray, ice_density: float = 917.0)\n", - " | Initialize the model with an array of z-coordinates.\n", - " | \n", - " | run_one_step(self, dt: float) -> numpy.ndarray\n", - " | Advance the model by one step of size dt.\n", - " | \n", - " | ----------------------------------------------------------------------\n", - " | Data descriptors defined here:\n", - " | \n", - " | __dict__\n", - " | dictionary for instance variables\n", - " | \n", - " | __weakref__\n", - " | list of weak references to the object\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "help(SimpleGlacier)" ] }, { "cell_type": "code", - "execution_count": 364, + "execution_count": null, "id": "56c97ced-a05d-4423-955f-c12e85e24b2d", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Help on function run_one_step in module __main__:\n", - "\n", - "run_one_step(self, dt: float) -> numpy.ndarray\n", - " Advance the model by one step of size dt.\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "help(SimpleGlacier.run_one_step)" ] @@ -531,18 +454,10 @@ }, { "cell_type": "code", - "execution_count": 369, + "execution_count": null, "id": "3e62dcb7-d12f-4f5f-a720-46e17e4e17ca", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "10000000000\n" - ] - } - ], + "outputs": [], "source": [ "model = SimpleGlacier(np.arange(10), 10000000000)\n", "print(model.ice_density)" @@ -558,18 +473,10 @@ }, { "cell_type": "code", - "execution_count": 370, + "execution_count": null, "id": "4639ce75-4725-4db7-8e86-116a74e80a51", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "917.0\n" - ] - } - ], + "outputs": [], "source": [ "model = SimpleGlacier(np.arange(10))\n", "print(model.ice_density)" @@ -618,12 +525,14 @@ "id": "4d4b08d0-7027-4fae-909e-4fe8d43c2113", "metadata": {}, "source": [ - "Just kidding - here's a template, but feel free to draw your own owl :)" + "Just kidding - here's a template, but feel free to draw your own owl :)\n", + "\n", + "Note: where I've written pass, you will probably want to return something or save a new class attribute (self.whatever), which means you can remove the pass statement." ] }, { "cell_type": "code", - "execution_count": 52, + "execution_count": null, "id": "0fe24f77-be64-4235-88b6-b7f766d72be7", "metadata": {}, "outputs": [], @@ -646,9 +555,9 @@ " self.temperature = initial_temperature\n", "\n", " # We probably want to calculate dz --> try using np.gradient\n", - " self.dz = np.gradient(self.z)\n", - " # Note: I didn't realize this when I originally wrote the class, but we won't need dz\n", + " # Note: I didn't realize this when I originally wrote the class, but we won't actually need dz\n", " # Want to know why? Check out the documentation for np.gradient -> https://numpy.org/doc/stable/reference/generated/numpy.gradient.html\n", + " # (What does the second argument to np.gradient do?)\n", " \n", " # We'll need attributes for rho, c, and k\n", " # You could also store info about boundary conditions at this point, if you want\n", @@ -657,54 +566,37 @@ " self.k = 2.1\n", "\n", " # Let's store boundary conditions too\n", - " self.surface_temperature = -10.0\n", - " self.basal_heat_flux = 0.0\n", " \n", " # Maybe we should go ahead and calculate diffusivity right away?\n", - " self.kappa = self.calc_diffusivity()\n", " \n", " # Let's keep track of the elapsed time\n", - " self.time_elapsed = 0.0\n", "\n", " def calc_diffusivity(self) -> float:\n", " \"\"\"From above, kappa = k / (rho * c).\"\"\"\n", - " return self.k / (self.rho * self.c)\n", + " pass\n", "\n", " def calc_heat_flux(self) -> np.ndarray:\n", " \"\"\"The heat flux is -kappa * dT / dz.\"\"\"\n", " \n", " # How should we calculate the difference in temperature with depth? (hint: see dz, above)\n", - " temperature_gradient = np.gradient(self.temperature, self.z)\n", "\n", " # Are dT and dz the same size? Are they the same size as z?\n", - " assert temperature_gradient.shape == self.dz.shape == self.z.shape\n", "\n", " # Don't forget to apply boundary conditions! The heat flux at the bed should be zero, for now.\n", - " temperature_gradient[-1] = self.basal_heat_flux\n", "\n", - " return -self.kappa * temperature_gradient\n", + " pass\n", " \n", " def calc_divergence(self) -> np.ndarray:\n", " \"\"\"In 1D, divergence is just the derivative. yay!\"\"\"\n", - " heat_flux = self.calc_heat_flux()\n", - " \n", - " flux_divergence = np.gradient(heat_flux, self.z)\n", - " \n", - " return flux_divergence\n", + " pass \n", " \n", " def run_one_step(self, dt: float):\n", " \"\"\"Advance the model by one step of size dt.\"\"\"\n", - " flux_divergence = self.calc_divergence()\n", - "\n", + " \n", " # updated temperature = current temperature - the divergence * dt\n", - " updated_temperature = self.temperature - flux_divergence * dt\n", "\n", " # Don't forget to apply boundary conditions! The temperature at the surface is equal to a fixed value.\n", - " updated_temperature[0] = self.surface_temperature\n", - "\n", - " self.temperature = updated_temperature\n", - "\n", - " self.time_elapsed += dt" + " " ] }, { @@ -717,21 +609,10 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": null, "id": "d74164bf-7cbe-47cf-a825-9bc249684fff", "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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tByNfsvsnnvuUb9+/bR9+3YdPXpU5eXl9nb06NEmbW7EiBFatmyZVq1apaeeekpbtmzR4MGD7aBSWlqqiIgIRUdH+zwvISFBpaWlds3pAPV98fHxds3Z5Ofn22uOLMtScnJyE14ZAABoSRo9Q7R792797//+ry677LJA9OPjl7/8pf1zSkqK+vXrp65du+qdd97Rrbfees7nGWPkcrnsx9//+Vw1Z5o5c6amT59uP/Z6vYQiAADaqEbPEKWmpurLL78MRC8N6ty5s7p27ardu3dLkhITE1VTU6Py8nKfurKyMiUkJNg1hw4dqneuw4cP2zVn43a7FRUV5bMBAIC2ya8Zok8//dT+OScnRzNmzFBpaal69+6t8PBwn9o+ffo0bYffc+TIEe3fv1+dO3eWJPXt21fh4eEqKirSmDFjJEklJSXavn27nnzySUlSWlqaPB6PNm/erOuuu06StGnTJnk8Hr6GBAAASPIzEF111VVyuVw+i6jvvPNO++fTxxq7qLqystJntmnPnj0qLi5WTEyMYmJiNGfOHN12223q3Lmz9u7dq1mzZikuLk633HKLJMmyLE2YMEEzZsxQbGysYmJilJeXp969e9ufOuvVq5eGDx+uiRMnatGiRZKkSZMmKTMzk0+YAQAASX4Goj179gRk8I8++kiDBg2yH59eszNu3DgtXLhQn332mZYuXaqKigp17txZgwYN0vLlyxUZGWk/Z/78+QoLC9OYMWNUVVWlm266SUuWLFFoaKhds2zZMk2bNs3+NFpWVtZ5//YRAABwFpc587PzDVizZo3S09MVFuabpU6dOqX169c36u8QtSZer1eWZcnj8bCeCACAJvSzZ9dqZ4lXS++8Tjde3qlJz+3v63ejF1UPGjTorB+v93g8PrM9AAAArUWjA9G5Pq5+5MgRdejQoUmaAgAAaE5+/x2i03/3x+Vyafz48XK73fax2tpaffrpp3xqCwAAtEp+ByLLsiT9e4YoMjJS7du3t49FRESof//+mjhxYtN3CAAAEGB+B6LFixdLkrp166a8vDzeHgMAAG1Go7+6Y/bs2ZL+/degd+3aJZfLpcsvv/ys3xcGAADQGjR6UbXX61V2drYuueQSDRgwQDfeeKMuueQS3X777fJ4PIHoEQAAIKAaHYjuuusubdq0SW+//bYqKirk8Xj09ttv66OPPmINEQAA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cDw+ZQYAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQAAByPQAQALcCRI0cUHx+vvXv3+uyvqanRjBkzlJeXp5qamiYd8+c//7mefvrpJj0n0FoRiADI5XKddxs/fnywWwyYgQMHKjc3N9htKD8/X6NGjVK3bt189i9fvlzXXHONrr/+er3yyit+n6+0tFQ5OTn60Y9+JLfbreTkZI0aNUr/+Mc/7JpHHnlEc+fOldfrbarLAFqtsGA3ACD4SkpK7J+XL1+uRx55RLt27bL3tW/fPhht/WA1NTWKiIhoNWNWVVXppZde0sqVK+sdq6urU3h4uGpra1VXV+fX+fbu3avrr79eHTt21JNPPqk+ffro5MmTevfddzVlyhR98cUXkqQ+ffqoW7duWrZsme69994f1DvQZhgA+J7Fixcby7Lq7a+rqzNPPPGE6d69u2nXrp3p06eP+ctf/uJTM2DAADN16lRz3333mY4dO5r4+HizaNEiU1lZacaPH28uvvhi86Mf/cisXLnS5zlTpkwxU6ZMMZZlmZiYGPPQQw+Zuro6v8c+fY7777/fxMbGmhtvvNEYY8zf//53c/3119vnHTlypPnyyy/t540bN85I8tn27NljunbtaubPn+9zbVdeeaWZPXt2g2P6c5/O9MYbb5i4uLizHjtx4oS57777TG5urjlx4sR5z3PaiBEjzCWXXGIqKyvrHSsvL/d5PGfOHPPTn/7Ur/MCbRlvmQHwy8MPP6zFixdr4cKF2rFjh+6//37dfvvtWr16tU/dyy+/rLi4OG3evFk5OTm699579Ytf/ELp6enatm2bhg0bpuzsbH333Xc+zwkLC9OmTZv0+9//XvPnz9eLL77YqLFPn+Of//ynFi1aJEk6fvy4pk+fri1btugf//iHQkJCdMstt9gzLc8++6zS0tI0ceJElZSUqKSkRMnJyX7fk7ON6e99+r41a9aoX79+Zz3mdrv1zDPPaP78+XK73Q32dPToURUWFmrKlCnq0KFDveMdO3b0eXzddddp8+bNqq6ubvDcQJsW7EQGoGU52wxRZWWladeunVm/fr3P/gkTJphf/epX9uMBAwaYG264wX586tQp06FDB5OdnW3vKykpMZLMhg0b7Of06tXLZ0boN7/5jenVq5ffYw8YMMBcddVVDV5bWVmZkWQ+++wzn57vu+8+nzp/Z4jOHNPf+3Smm2++2dx5550N9u+PTZs2GUnmzTff9Kv+k08+MZLM3r17m2R8oLViDRGABu3cuVMnTpzQ0KFDffbX1NTo6quv9tnXp08f++fQ0FDFxsaqd+/e9r6EhARJUllZmb2vf//+crlc9uO0tDQ99dRTqq2t9Xvss82w/Otf/9Jvf/tbbdy4Ud9++609M7Rv3z6lpKT4ff3ncuaYjblP31dVVaV27dpdcD+SZIyRJJ/7eT6n14d9f8YOcCICEYAGnQ4S77zzji655BKfY2e+jRMeHu7z2OVy+ew7/ULt7wJhf8c+29tDo0aNUnJysl544QUlJSWprq5OKSkpDX58PSQkxA4Wp508ebJe3ZljNuY+fV9cXJzKy8vP25O/evToIZfLpc8//1yjR49usP7o0aOSpE6dOjXJ+EBrRSAC0KArrrhCbrdb+/bt04ABA5r8/Bs3bqz3uEePHgoNDf3BYx85ckSff/65Fi1apJ/+9KeSpHXr1tWri4iIUG1trc++Tp06+Xzyzuv1as+ePQ2O+UN7vfrqq/Xqq6/6XX8+MTExGjZsmJ577jlNmzatXmirqKjwWUe0fft2denSRXFxcU0yPtBaEYgANCgyMlJ5eXm6//77VVdXpxtuuEFer1fr16/XxRdfrHHjxl3Q+ffv36/p06fr7rvv1rZt2/SHP/xBTz311AWNHR0drdjYWP3pT39S586dtW/fPj344IP16rp166ZNmzZp7969uvjiixUTE6PBgwdryZIlGjVqlKKjo/Xb3/5WoaGhAbtPw4YN08yZM1VeXq7o6OhG3Lmz++Mf/6j09HRdd911evTRR9WnTx+dOnVKRUVFWrhwoT7//HO7du3atcrIyLjgMYHWjkAEwC+PPfaY4uPjlZ+fr6+++kodO3bUNddco1mzZl3wue+44w5VVVXpuuuuU2hoqHJycjRp0qQLGjskJEQFBQWaNm2aUlJS1LNnT/3+97/XwIEDfery8vI0btw4XXHFFaqqqtKePXs0c+ZMffXVV8rMzJRlWXrsscf8miH6ob327t1b/fr10//8z//o7rvv9muc8+nevbu2bdumuXPnasaMGSopKVGnTp3Ut29fLVy40K47ceKEVqxYoXffffeCxwRaO5c5841yAGhGAwcO1FVXXaVnnnkm2K0E1cqVK5WXl6ft27crJKR5/iLKc889p7feekvvvfdes4wHtGTMEAFAC/Czn/1Mu3fv1sGDBxv1t5AuRHh4uP7whz80y1hAS0cgAoAW4r777mvW8b7/tiTgdLxlBgAAHI+v7gAAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI5HIAIAAI73/wHDgjrWrsPGJgAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# The Greenland ice sheet is 3,053 m thick at the summit!\n", "z = np.arange(3053)\n", @@ -761,57 +642,10 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": null, "id": "d216e3d2-986e-4d3f-82c1-e6ed2fbfbc43", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0.05475818525543331 years.\n", - "54.81294344068874 years.\n", - "109.57112869612205 years.\n", - "164.32931395155535 years.\n", - "219.08749920698867 years.\n", - "273.84568446242196 years.\n", - "328.6038697178553 years.\n", - "383.3620549732886 years.\n", - "438.1202402287219 years.\n", - "492.87842548415523 years.\n", - "547.6366107395885 years.\n", - "602.3947959950218 years.\n", - "657.1529812504551 years.\n", - "711.9111665058884 years.\n", - "766.6693517613218 years.\n", - "821.4275370167551 years.\n", - "876.1857222721884 years.\n", - "930.9439075276217 years.\n", - "985.7020927830549 years.\n", - "1040.4602780384882 years.\n", - "1095.2184632939216 years.\n", - "1149.9766485493549 years.\n", - "1204.7348338047882 years.\n", - "1259.4930190602215 years.\n", - "1314.2512043156548 years.\n", - "1369.0093895710881 years.\n", - "1423.7675748265215 years.\n", - "1478.5257600819548 years.\n", - "1533.283945337388 years.\n", - "1588.0421305928214 years.\n" - ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkQAAAG0CAYAAADTmjjeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/TGe4hAAAACXBIWXMAAA9hAAAPYQGoP6dpAABG5ElEQVR4nO3deXhU9d3//9dkm+yTjWwQAgpSbMAFagguLLLeAmJt9Sq/pnBXcQMUgbaitnLbCmq/Shd6U2otVIvFu7dSeytNxaIgsoPIKsUKBEIWIJPJPpPl/P4IHBiSQCKTTJLzfFzXXJk55zPnvM+5sPPq53zO59gMwzAEAABgYQH+LgAAAMDfCEQAAMDyCEQAAMDyCEQAAMDyCEQAAMDyCEQAAMDyCEQAAMDygvxdQGdRX1+vkydPKioqSjabzd/lAACAFjAMQ2VlZUpNTVVAQPP9QASiFjp58qTS0tL8XQYAAPgKjh8/rh49ejS7nkDUQlFRUZIaTmh0dLSfqwEAAC1RWlqqtLQ083e8OQSiFjp3mSw6OppABABAJ3O54S4MqgYAAJZHIAIAAJZHIAIAAJZHIAIAAJZHIAIAAJZHIAIAAJZHIAIAAJZHIAIAAJZHIAIAAJZHIAIAAJZnqUD03//93+rdu7dCQ0M1aNAgffzxx/4uCQAAdACWCURvvvmmZs+eraeeekqffvqpbr31Vo0fP165ubn+Lg0AAPiZzTAMw99FtIfMzEzdeOONWrp0qbmsf//+mjx5shYtWnTZ75eWlsrhcMjlcvn04a4nnJUKDLCpW6RdQYGWyacAALSLlv5+W+Jp9x6PRzt37tQTTzzhtXzMmDHatGlTk99xu91yu93m59LS0jap7dn/O6D3DxTKZpMSIu1Kjg5VUrRdSdGhDe8doeb75OhQRYcFXfaJvQAAoHUsEYhOnz6turo6JSUleS1PSkpSQUFBk99ZtGiR/uu//qvNa6urNxQUYFNtvaFTZW6dKnNrb17z7UODA5QUHWq+ks+Gp6ToUCU7GkJTtyi7QoMD27x2AAC6CksEonMu7lkxDKPZ3pb58+drzpw55ufS0lKlpaX5vKZXp31D9fWGTle4VVTqVoGrWgWl1SoqbfhbUOpWoatahWXVKqmsUXVNvY6dqdSxM5WX3G5sePAFoamhp8mr98kRqrjwEAUE0NsEAIAlAlFCQoICAwMb9QYVFRU16jU6x263y263t0d5CgiwKTEqVIlRocro7mi2XXVNnQpLq1VY6lZBaXVDUDobnC5c7qmtl7OyRs7KGn1eUNbs9oIDG/abdFEv04WX7JIdoQoPscQ/EwCAhVnily4kJESDBg3S2rVrddddd5nL165dqzvvvNOPlbVOaHCg0uMjlB4f0WwbwzBUUlmjwrJqFbiqGweosmoVuNw6U+FWTZ2hvJIq5ZVUXXK/UfYgs4cpMdpuBqXEqPOX6RIiQxgUDgDotCwRiCRpzpw5ys7O1uDBg5WVlaXf/e53ys3N1UMPPeTv0nzKZrMpNiJEsREh+lpy86Ppa+rqdars4p4md8Pfs8Gp0FWtCk+dyty1Kisq1xdF5c1uL+DcoHAzKNnPBqjzPU1J0aGKDmVQOACg47FMILr33nt15swZPfvss8rPz1dGRobWrFmj9PR0f5fmF8GBAUqNCVNqTNgl25VV16iwiaBUcLbnqbC0WkVlbtXVGyoqc6uozC3J1ez2QoMDzo5luvASXcNlunPLE6PtsgcxKBwA0H4sMw/RlWqreYi6grp6Q2cq3Cp0uS8Yz3QuQLnNAOWqqmnxNuMiQhoFpYYAdX58UyyDwgEAl8E8RGg3gRcMCh+gyw8KP38nnfvsnXTn76orLHXLU1uv4gqPiis8Opjf/H7PDQq/eCD4xQPEGRQOALgcfinQblozKNwrKJ3teSq64I660+Welg8KDw1q1MvUMK4pTCkOpiAAABCI0MFcOCi8f0rzXZue2nqdKm+Yt+n8nE3V5lxO56YjqPTUqay6VmXV5Tp8iUHhIYEBSoy2nw1IZ4NSdKgZmFIcYeoWZVcgoQkAuiQCETqlkKAAdY8JU/cWDQo/O/XABZNe5p8NTfmuap0qd8tTV68TziqdcFZJcja5rYZLgw2X5s4HJe8AlRQdqpAgph8AgM6GQIQuLSo0WFGhweqTGNVsm5q6ehWVuVXgqlK+q2GMU/7Z8FTgOj/mqa7eUP7ZdbuPN7/PhMiGnqbGwamhpyk5OlRhIdxFBwAdCYEIlhccePneprp6Q2fK3WYgKnBVKf+iwJTvapgl/HS5W6fL3dqb1/z0AzHhwV6X5JKjwxqFp6jQ4LY4XABAEwhEQAsEBtiUeHaiyeuaeaSdYRhyVtYo31V1vpfJ7G06v6zSU6eSyhqVXObRKpH2IDMgXdzblOIIU6ojTNFhTHQJAL5AIAJ8xGazKS4iRHERIfp6atPTDxiGoTJ37QWB6aLLdBfM2VTurtUXl5khPDwkUKkxDb1LqY6GiTZTYs69D1VqTJhCg7k8BwCXQyAC2pHNZlN0aLCiQ4N1TVLz45oqPbXm5bh885JcQy/TyZKGz8UVHlV66i4bmmLDg8+GpvMhKcURas5UnhRl5zl0ACyPQAR0QOEhQbqqW6Su6hbZbJsqT53yz/YwnSyp0smShtCUV9KwLL+kShWeOjkra+SsrNH+k6VNbifAJiVGhSo1JlQpMWFKdYQ2ClDxESFcmgPQpRGIgE4qLCTwkqHJMAyVVtXqpKvqbFBqCEn5ruqzoamhx6mmzjDncVJuSZPbCgkKMC/Lnb8k5315jkHgADozAhHQRdlsNjnCg+UID252ksv6ekOny906ebZHyexduiBAnSpveJzKsTOVOnamstn9RdmDlBoTpu6xDXfsXfi3R0yYEiLtzAYOoMPi4a4txMNdYVWe2noVljZclruwdym/pNoMUC15cG9IUIBSHaHqERveKDB1PzuuibFMAHyNh7sC8ImQoAClxYUrLS682TYV7lqzVynPWaW8ksqzf6uU56xSQWnDHE1Hz1TqaDO9TAE2KTk61AxIPWLDG4Um7pgD0FYIRACuWIQ9SH0So5qdEbymrl4FrmqduCAk5ZVUmu9PllTLU1evk65qnXRVa3szj09JiAzxCkhevU2xYYpmHBOAr4hABKDNBQdeupfp3FimEyUNz5NrqpepwlOn0+UenS736LMTTc8CHhUapB6x4UqLDVPPs/tLiwtTWmy4esSG88gUAM1iDFELMYYI8B/DMOSqqrmoh6nh74mzwclZeflxTN2i7EqLDWsISrHnw1JaXDhjmIAuijFEALoMm82mmPAQxYSHKKN707OAV7hrdbKkSsedlTpeXKXjxZVe78vctTpV5tapMrd2NTG9QGCATakxoQ0BKTZcPePD1eOC8JQQyVxMQFdGIALQJUTYg9Q3KUp9m5gB/FwP0/Hic4HJOyydcFbJU1d/9nOVpDONthEWHKgeF1yKOxeW0uPD1TMuXOEh/M8p0JnxXzCALu/CHqYBPRr3MNXXGyoqc58PS8VVyj0bmk4UVyq/tFpVNXU6XFSuw808JqVblF294sPVMy6i4W98uHrFRyg9Plwx4SFtfYgArhBjiFqIMUSAdXlq683LcblnA9O5sHSsuFIllxm/FB0apF4JEeoZ1xCSLgxLiVF2LsUBbYgxRADgIyFBAeqVEKFeCRFNrndV1uhYccXZ2bwrzFm9jxVXqLDUrdLqWu054dKeJu6OCw0OUHrcuZAUrp7xDT1M6XERSo1hoDfQXghEAHCFHOHBGhgeo4E9Yhqtq/LUKbe4UkfPVCj3bEg6F5jySqpUXVOvQ4VlOlRY1ui7QQE29YwLV++EiIZXt4a/VyVEKimaniXAlwhEANCGwkIC1S85Sv2SGw/2rqmrV56zqiEsFVfq6OlK5RZX6OiZhktzntp6fXm6Ql+ermj03fCQQPWKbwhJV50NTFd1i1Tv+Ag5wpmgEmgtAhEA+ElwYPOX4urrDRWUVuvo2UB05IJXbnGlKj11OpBfqgP5pY2+Gx8R4tWr1BCYIpUeH87jT4BmMKi6hRhUDaCjqKmr1/HiSh05XaEvT50LTOU6crphzFJzbDYp1RGmqxMj1adbpPoknn/FRXAnHLqmlv5+E4haiEAEoDOocNd69SYdOdvD9OWpcpVV1zb7vbiIEPXpFqmrEyN09QVhKdURpoAAxiqh8yIQ+RiBCEBnZhiGiis8+vJ0hb4oKvd65ZVUNfu9sOBAXZ0Y4dWjdHW3SKXHRygkiDvg0PERiHyMQASgq6r01OrLUxcFpVPlOnq6QrX1Tf9EBAXY1CshQv2SonRNUpT6JUeqX3K0esaFK5AeJXQgBCIfIxABsJqaunodO1Opf59qCEn/PhuUvigqV6Wnrsnv2IMC1DcpUv2SotUvOfJsWIpScnQo0wTALwhEPkYgAoAGhmEo31WtfxWW6V+FZTpUUG6+d9fWN/md6NAg9UuOMgNSv7N/eawJ2hqByMcIRABwaXX1hnKLK3Wo4FxQaphw8sjpCtU1c+ktKdqua1OidW1qtK5Nceja1Gilx4UzkBs+QyDyMQIRAHw17to6fXmqwgxI/zr794Sz6cHc4SGB6p8Srf4pUWZI6pcUpbAQ5lBC6xGIfIxABAC+Ve6u1aGCUh3IL9OBkw2TTH6eX9rkZbcAm3RVt8gLepOildHdwfxJuCwCkY8RiACg7dXW1evomQrtPxuQDpxseJ2p8DTZvntMmAb2cGhgjxgN7OFQRneHHGE8ugTnEYh8jEAEAP5hGIZOlbm1/1xAOvv3SBPPeJOkXvHhZkAa0N2hr3d3KNLOk6qsikDkYwQiAOhYSqtrtC/Ppb0nXNqT59KeEyU6Xtx4XJLNJvXpFqkBPRwa2N2hG3rG6trUaAUHMrGkFRCIfIxABAAdn7PCo715Lu09G5D2nnDppKu6UTt7UIAG9nDoxp6xuqFnrG5Mj1FiVKgfKkZbIxD5GIEIADqnU2Vu7c0r0Z4TLn12vESfHi9RSWVNo3Y9YsN0Y89Y3dgzRjemx6p/Cr1IXQGByMcIRADQNRiGoS9PV2jXMad25Zbo01ynDhWW6eJfQ3tQgK7rEaObesfppt5xGpQeqwjGInU6BCIfIxABQNdVVl2jz467tCvXqV25Tn2aWyJXlXcvUmCATRndHcrsHafM3nEanB4nRzh3tHV0BCIfIxABgHXU1zf0Iu04WqxtR4q19Uix8kq8B2zbbNLXkqPNgDTkqnjFMi9Sh0Mg8jECEQBY2wlnpbYdKTZfX15027/NJn09NVq39OmmW/okaHCvWIUGM7u2vxGIfIxABAC4UFFZtRmOtnx5Rv8qLPdabw8K0Dd6xenmPgm6tW+Crk2J5hltftDS3+8OPXx+wYIFstlsXq/k5GRzvWEYWrBggVJTUxUWFqbhw4dr//79Xttwu92aNWuWEhISFBERoUmTJunEiRPtfSgAgC4mMSpUEwam6tk7M/T+48O07cnb9Yt7r9fdN/ZQUrRd7tp6bfzitF7I+VwTfr1Rg362VjNW7tL/7DiuU2Vuf5ePi3T44fJf//rX9cEHH5ifAwPPdz+++OKLevnll7VixQpdc801+tnPfqbRo0fr0KFDioqKkiTNnj1b//d//6dVq1YpPj5ec+fO1YQJE7Rz506vbQEAcCUSo0M1+YbumnxDdxmGoX+fKtfGw6e18Ysz2vLlGTkra/Te3ny9tzdfknRdD4dGfi1JI7+WqK+n0nvkbx36ktmCBQv017/+Vbt37260zjAMpaamavbs2frRj34kqaE3KCkpSS+88IIefPBBuVwudevWTa+//rruvfdeSdLJkyeVlpamNWvWaOzYsS2uhUtmAICvqqauXntOlGjDv07rw0NF2nPC5bU+McquEf0SNbJ/om7pk8Dt/T7U0t/vDn/GDx8+rNTUVNntdmVmZmrhwoW66qqrdOTIERUUFGjMmDFmW7vdrmHDhmnTpk168MEHtXPnTtXU1Hi1SU1NVUZGhjZt2nTJQOR2u+V2n+/SLC0tbZsDBAB0ecGBARqUHqdB6XF6fPQ1Kiqt1oeHirTu8yJ9fPi0isrcenPHcb2547hCggJ0W99u+o8Bybq9fxIPq20nHToQZWZm6rXXXtM111yjwsJC/exnP9PQoUO1f/9+FRQUSJKSkpK8vpOUlKRjx45JkgoKChQSEqLY2NhGbc59vzmLFi3Sf/3Xf/nwaAAAaJAYHap7v9FT936jp9y1ddr6ZbHWfd4QkHKLK/XBwUJ9cLBQwYE23dwnQeMzkjX62mTFcVt/m+nQgWj8+PHm+wEDBigrK0tXX321/vjHP2rIkCGSJJvN+5qrYRiNll2sJW3mz5+vOXPmmJ9LS0uVlpbW2kMAAOCS7EGBuu2abrrtmm56ZuK1+rygTH/fV6Ccffn6V2G5Pjp0Sh8dOqUnV+/TkKviNHFgqsYPSKHnyMc6dCC6WEREhAYMGKDDhw9r8uTJkhp6gVJSUsw2RUVFZq9RcnKyPB6PnE6nVy9RUVGRhg4desl92e122e123x8EAADNsNls6p8Srf4p0Zoz+hp9UVSunH35+vu+Au0/WapPvjijT744o5/8bb9u/1qiJt/QXcP7dZM9iJuErlSHvu3+Ym63WwcPHlRKSop69+6t5ORkrV271lzv8Xi0fv16M+wMGjRIwcHBXm3y8/O1b9++ywYiAAD8rU9ipGaO7Kv3Hr1VG34wQj8c10/XJEXKU1uvv+8r0IOv79RNz/1TT67eq53HitWB75Pq8Dr0XWbz5s3TxIkT1bNnTxUVFelnP/uZ1q9fr7179yo9PV0vvPCCFi1apOXLl6tv375auHChPvroI6/b7h9++GG9++67WrFiheLi4jRv3jydOXOm1bfdc5cZAKAjMAxDB/PL9NfdeXpnd54KS8/fANQ3MVLfuamnvnljd8WEM95I6iJ3mZ04cULf+c53dPr0aXXr1k1DhgzRli1blJ6eLkn64Q9/qKqqKj3yyCNyOp3KzMzU+++/b4YhSVq8eLGCgoJ0zz33qKqqSrfffrtWrFjBHEQAgE7JZrPp2tRoXZsarR+N+5q2fHlGb+/K05q9+TpcVK5n3z2gF3I+1x0DUvSdzJ4anB572XGz6OA9RB0JPUQAgI6stLpG73yap5Vbc/V5QZm5vG9ipL5/S2/ddUN3Sz5bjWeZ+RiBCADQGRiGoc9OuPTnrbn622cnVVVTJ0mKiwjRd4ekK3tIurpFWeemIQKRjxGIAACdTWl1jf5n+3Et/+So8kqqJEkhgQGafEOqHhx2ta7uFunnCtsegcjHCEQAgM6qtq5e/9hfqFc+/lK7j5dIkgJs0sTrUjVrZF/1Sey6wYhA5GMEIgBAV7DzmFNLP/q3PjhYKEmy2aSJA1P16O191Ccx6jLf7nwIRD5GIAIAdCX78lz65T8Pa+2B88HoWzf20Lyx/ZQUHern6nyHQORjBCIAQFe0L8+lX/3zsN4/G4zCggP14LCr9MBtVyk8pEPPztMiBCIfIxABALqyXblO/ezdA9qVWyJJSoyy66k7+mvSdamdeh4jApGPEYgAAF2dYRhas7dAz+cc1PHihrvSbu2boJ9NzlB6fISfq/tqWvr73ameZQYAANqOzWbTHQNT9MGcYZo7+hqFBAXo48OnNWbxBi396N+qq++6fSgEIgAA4MUeFKhZt/dVzmO3aujV8XLX1uuFnM9177LNOl5c6e/y2gSBCAAANOmqbpFaeX+mXvzWQEXag7TjmFPjf/mx/nfnCX+X5nMEIgAA0CybzaZ7Bqfp74/dqsHpsSp312reXz7TE2/tUfXZx4J0BQQiAABwWWlx4XrzwSzNHX2NbDZp1fbjuvd3W3Ty7CNBOjsCEQAAaJHAAJtm3d5Xf/zPmxQTHqzPjpdo0pJPtC/P5e/SrhiBCAAAtMpt13TT/828RV9LjtLpcrfuXbZZHx8+5e+yrgiBCAAAtFpaXLj+8lCWbu4TrwpPnf5z+Xa9u+ekv8v6yghEAADgK4kKDdbyaTdp0nWpqq039Niq3crZl+/vsr4SAhEAAPjKQoIC9It7r9fdN/ZQXb2hmW98aj4wtjMhEAEAgCsSEGDTi98aqDuvb+gpmvnGLn2a6/R3Wa1CIAIAAFcsMMCml759nW7/WqLctfWa/toOnXB2nlmtCUQAAMAnggID9Kvv3KD+KdE6Xe7R/X/c0WkmbyQQAQAAn4mwB+nVqYOVEBmizwvK9LP3Dvi7pBYhEAEAAJ9KjQnTy/dcL0n605bcTnHnGYEIAAD43G3XdNODw66SJD25ep+cFR4/V3RpBCIAANAm5o7up35JUSqu8GjR3w/6u5xLIhABAIA2ERIUoIXfzJAk/c+OE9p2pNjPFTWPQAQAANrMoPQ4feemNEnS838/KMMw/FxR0whEAACgTT0+6hqFBgdoV26J1n1e5O9ymkQgAgAAbSoxOlRTh/aSJL30/r86ZC8RgQgAALS5h267WmHBgTqQX6otX3a8sUQEIgAA0OZiI0J096DukqQ/fHLEz9U0RiACAADtYtrQ3pKkDw4WKq+kys/VeCMQAQCAdtEnMVKZveNkGNLfdp/0dzleCEQAAKDd3HVDw2Wz1Z+e6FCDqwlEAACg3YwfkKKQwAD9q7Bc/yos93c5JgIRAABoN46wYN3cJ16S9OGhjjMnEYEIAAC0q+H9EiVJHxGIAACAVQ3v102StOOoU2XVNX6upgGBCAAAtKv0+Aj1jAtXbb2hXbkl/i5HEoEIAAD4wY09YyRJn+Y6/VvIWQQiAADQ7m5Mj5UkeogAAIB13dizIRDtznV2iPmICEQAAKDd9U2KVGCATaXVtSosdfu7HAIRAABof/agQPWKD5ckHS4q83M1fg5EGzZs0MSJE5Wamiqbzaa//vWvXusNw9CCBQuUmpqqsLAwDR8+XPv37/dq43a7NWvWLCUkJCgiIkKTJk3SiRMnvNo4nU5lZ2fL4XDI4XAoOztbJSUlbXx0AADgUvomRklSh5ix2q+BqKKiQtddd52WLFnS5PoXX3xRL7/8spYsWaLt27crOTlZo0ePVlnZ+SQ5e/ZsrV69WqtWrdLGjRtVXl6uCRMmqK6uzmwzZcoU7d69Wzk5OcrJydHu3buVnZ3d5scHAACa1zcpUpL0RQfoIZLRQUgyVq9ebX6ur683kpOTjeeff95cVl1dbTgcDuO3v/2tYRiGUVJSYgQHBxurVq0y2+Tl5RkBAQFGTk6OYRiGceDAAUOSsWXLFrPN5s2bDUnG559/3uL6XC6XIclwuVxf9RABAMAF/nfHcSP9R+8a/98rWy7f+Ctq6e93hx1DdOTIERUUFGjMmDHmMrvdrmHDhmnTpk2SpJ07d6qmpsarTWpqqjIyMsw2mzdvlsPhUGZmptlmyJAhcjgcZpumuN1ulZaWer0AAIDvpMaESZJOllT5uZIOPKi6oKBAkpSUlOS1PCkpyVxXUFCgkJAQxcbGXrJNYmJio+0nJiaabZqyaNEic8yRw+FQWlraFR0PAADwlhoTKkk66ary+633HTYQnWOz2bw+G4bRaNnFLm7TVPvLbWf+/PlyuVzm6/jx462sHAAAXEqyoyEQVdfUy1np32eaddhAlJycLEmNenGKiorMXqPk5GR5PB45nc5LtiksLGy0/VOnTjXqfbqQ3W5XdHS01wsAAPiOPShQCZF2Sf6/bNZhA1Hv3r2VnJystWvXmss8Ho/Wr1+voUOHSpIGDRqk4OBgrzb5+fnat2+f2SYrK0sul0vbtm0z22zdulUul8tsAwAA/CMhMkSSdKbC49c6gvy58/Lycn3xxRfm5yNHjmj37t2Ki4tTz549NXv2bC1cuFB9+/ZV3759tXDhQoWHh2vKlCmSJIfDofvuu09z585VfHy84uLiNG/ePA0YMECjRo2SJPXv31/jxo3T9OnTtWzZMknSAw88oAkTJqhfv37tf9AAAMAUG94QiEoqLRyIduzYoREjRpif58yZI0maOnWqVqxYoR/+8IeqqqrSI488IqfTqczMTL3//vuKiooyv7N48WIFBQXpnnvuUVVVlW6//XatWLFCgYGBZpuVK1fq0UcfNe9GmzRpUrNzHwEAgPYTF9EQiJx+7iGyGf4e1t1JlJaWyuFwyOVyMZ4IAAAfeWr1Xq3cmqvHbu+rx0df4/Ptt/T3u8OOIQIAAF1fR7lkRiACAAB+ExMeLEncdg8AAKwrwt4wnLnSU+vXOghEAADAb8JDGm6Cqqqpu0zLtkUgAgAAfhMW3BCIKj0EIgAAYFHhIQ2XzKoIRAAAwKrCQughAgAAFhdOIAIAAFZnDqrmLjMAAGBVIUENUcRTV+/XOghEAADAb4ICGqJITZ0hfz5NjEAEAAD8JjjQZr6vqycQAQAACwoKPB9FaglEAADAioICzvcQ1fhxHBGBCAAA+E3whT1EdfQQAQAACwoMsMl2tpOopp4eIgAAYFHBZ+80o4cIAABYVtDZO838GYiCWtP40KFD+vOf/6yPP/5YR48eVWVlpbp166YbbrhBY8eO1d133y273d5WtQIAgC7o3MDqDn/J7NNPP9Xo0aN13XXXacOGDfrGN76h2bNn66c//am++93vyjAMPfXUU0pNTdULL7wgt9vd1nUDAIAu4tyt9/6ch6hFPUSTJ0/WD37wA7355puKi4trtt3mzZu1ePFivfTSS3ryySd9ViQAAOi6zt1478eJqlsWiA4fPqyQkJDLtsvKylJWVpY8Hs8VFwYAAKzh3F1mhjr4oOqWhKEraQ8AAKzLdjYRdfgeoott27ZNH330kYqKilR/0QCol19+2SeFAQAAazh3yazej4mo1YFo4cKFevrpp9WvXz8lJSWZqU6S13sAAICWMC+ZdaYeol/+8pf6wx/+oGnTprVBOQAAwGoCOkCHSqsnZgwICNDNN9/cFrUAAAAL6giXzFodiB5//HH95je/aYtaAACABXXKQdXz5s3THXfcoauvvlrXXnutgoODvda//fbbPisOAAB0fedvu/efVgeiWbNm6cMPP9SIESMUHx/PQGoAAHBFzkWJTnWX2Wuvvaa33npLd9xxR1vUAwAALMYm/18ya/UYori4OF199dVtUQsAALCgAPNiUycaVL1gwQI988wzqqysbIt6AACAxZwbfuPHZ7u2/pLZr371K/373/9WUlKSevXq1WhQ9a5du3xWHAAA6Po6zcNdLzR58uQ2KAMAAFjV+ZmqO9Gg6meeeaYt6gAAABbVES6ZtXoMUUv4M+EBAIDOxbxk1tEHVffv319vvPGGPB7PJdsdPnxYDz/8sF544QWfFAcAALo+2/lE5DctumT2m9/8Rj/60Y80Y8YMjRkzRoMHD1ZqaqpCQ0PldDp14MABbdy4UQcOHNDMmTP1yCOPtHXdAACgi7DJ/5M8tygQjRw5Utu3b9emTZv05ptv6o033tDRo0dVVVWlhIQE3XDDDfre976n7373u4qJiWnjkgEAAHyrVYOqhw4dqqFDh7ZVLQAAAH7RJoOqAQAAOhMCEQAAsDwCEQAAsDy/BqINGzZo4sSJSk1Nlc1m01//+lev9dOmTZPNZvN6DRkyxKuN2+3WrFmzlJCQoIiICE2aNEknTpzwauN0OpWdnS2HwyGHw6Hs7GyVlJS08dEBAIDOwq+BqKKiQtddd52WLFnSbJtx48YpPz/ffK1Zs8Zr/ezZs7V69WqtWrVKGzduVHl5uSZMmKC6ujqzzZQpU7R7927l5OQoJydHu3fvVnZ2dpsdFwAA6Fxa/egOSaqvr9cXX3yhoqIi1dfXe6277bbbWryd8ePHa/z48ZdsY7fblZyc3OQ6l8ulV199Va+//rpGjRolSfrTn/6ktLQ0ffDBBxo7dqwOHjyonJwcbdmyRZmZmZKkV155RVlZWTp06JD69evX4noBAEDX1OpAtGXLFk2ZMkXHjh1r9IgOm83m1TPjCx999JESExMVExOjYcOG6bnnnlNiYqIkaefOnaqpqdGYMWPM9qmpqcrIyNCmTZs0duxYbd68WQ6HwwxDkjRkyBA5HA5t2rSp2UDkdrvldrvNz6WlpT49LgAA0HG0+pLZQw89pMGDB2vfvn0qLi6W0+k0X8XFxT4tbvz48Vq5cqXWrVunl156Sdu3b9fIkSPNoFJQUKCQkBDFxsZ6fS8pKUkFBQVmm3MB6kKJiYlmm6YsWrTIHHPkcDiUlpbmwyMDAAAdSat7iA4fPqz//d//VZ8+fdqiHi/33nuv+T4jI0ODBw9Wenq63nvvPX3zm99s9nuGYZhPzpXk9b65NhebP3++5syZY34uLS0lFAEA0EW1uocoMzNTX3zxRVvUclkpKSlKT0/X4cOHJUnJycnyeDxyOp1e7YqKipSUlGS2KSwsbLStU6dOmW2aYrfbFR0d7fUCAABdU4t6iPbs2WO+nzVrlubOnauCggINGDBAwcHBXm0HDhzo2wovcObMGR0/flwpKSmSpEGDBik4OFhr167VPffcI0nKz8/Xvn379OKLL0qSsrKy5HK5tG3bNt10002SpK1bt8rlcvEYEgAAIKmFgej666+XzWbzGkT9/e9/33x/bl1rB1WXl5d79TYdOXJEu3fvVlxcnOLi4rRgwQLdfffdSklJ0dGjR/Xkk08qISFBd911lyTJ4XDovvvu09y5cxUfH6+4uDjNmzdPAwYMMO8669+/v8aNG6fp06dr2bJlkqQHHnhAEyZM4A4zAAAgqYWB6MiRI22y8x07dmjEiBHm53NjdqZOnaqlS5dq7969eu2111RSUqKUlBSNGDFCb775pqKioszvLF68WEFBQbrnnntUVVWl22+/XStWrFBgYKDZZuXKlXr00UfNu9EmTZp0ybmPAACAtdiMi++dv4wNGzZo6NChCgryzlK1tbXatGlTq+Yh6kxKS0vlcDjkcrkYTwQAgA+NXbxBhwrL9Mb9mRraJ8Gn227p73erB1WPGDGiydvrXS6XV28PAABAa7Sqh8bHWh2Imrtd/cyZM4qIiPBJUQAAwDouMQtOu2nxPETn5v2x2WyaNm2a7Ha7ua6urk579uzhri0AANAptTgQORwOSQ09RFFRUQoLCzPXhYSEaMiQIZo+fbrvKwQAAGhjLQ5Ey5cvlyT16tVL8+bN4/IYAADoMlr96I5nnnlGUsNs0IcOHZLNZtM111zT5PPCAAAAOoNWD6ouLS1Vdna2unfvrmHDhum2225T9+7d9d3vflcul6stagQAAGhTrQ5E999/v7Zu3ap3331XJSUlcrlcevfdd7Vjxw7GEAEAgE6p1ZfM3nvvPf3jH//QLbfcYi4bO3asXnnlFY0bN86nxQEAALSHVvcQxcfHm3ecXcjhcCg2NtYnRQEAALSnVgeip59+WnPmzFF+fr65rKCgQD/4wQ/04x//2KfFAQAAtIdWXzJbunSpvvjiC6Wnp6tnz56SpNzcXNntdp06dcp8orwk7dq1y3eVAgAAtJFWB6LJkye3QRkAAAD+85XnIQIAAOgqWj2GSJJKSkr0+9//XvPnzzeffL9r1y7l5eX5tDgAAID20Ooeoj179mjUqFFyOBw6evSopk+frri4OK1evVrHjh3Ta6+91hZ1AgAAtJlW9xDNmTNH06ZN0+HDhxUaGmouHz9+vDZs2ODT4gAAANpDqwPR9u3b9eCDDzZa3r17dxUUFPikKAAAgPbU6kAUGhqq0tLSRssPHTqkbt26+aQoAACA9tTqQHTnnXfq2WefVU1NjSTJZrMpNzdXTzzxhO6++26fFwgAAKzBMPy371YHov/3//6fTp06pcTERFVVVWnYsGHq06ePoqKi9Nxzz7VFjQAAAG2q1XeZRUdHa+PGjVq3bp127dql+vp63XjjjRo1alRb1AcAANDmWh2Izhk5cqRGjhzpy1oAAAD8olWBqL6+XitWrNDbb7+to0ePymazqXfv3vrWt76l7Oxs2Wy2tqoTAACgzbR4DJFhGJo0aZLuv/9+5eXlacCAAfr617+uY8eOadq0abrrrrvask4AAIA20+IeohUrVmjDhg365z//qREjRnitW7dunSZPnqzXXntN3/ve93xeJAAAQFtqcQ/Rn//8Zz355JONwpDUMJ7oiSee0MqVK31aHAAAQHtocSDas2ePxo0b1+z68ePH67PPPvNJUQAAAO2pxYGouLhYSUlJza5PSkqS0+n0SVEAAADtqcWBqK6uTkFBzQ85CgwMVG1trU+KAgAAaE8tHlRtGIamTZsmu93e5Hq32+2zogAAANpTiwPR1KlTL9uGO8wAAEBn1OJAtHz58rasAwAAwG9a/XBXAACAroZABAAALI9ABAAALI9ABAAALI9ABAAALI9ABAAAOgRDht/2TSACAAB+ZbPZ/F0CgQgAAIBABAAALI9ABAAALI9ABAAALM+vgWjRokX6xje+oaioKCUmJmry5Mk6dOiQVxvDMLRgwQKlpqYqLCxMw4cP1/79+73auN1uzZo1SwkJCYqIiNCkSZN04sQJrzZOp1PZ2dlyOBxyOBzKzs5WSUlJWx8iAADoBPwaiNavX68ZM2Zoy5YtWrt2rWprazVmzBhVVFSYbV588UW9/PLLWrJkibZv367k5GSNHj1aZWVlZpvZs2dr9erVWrVqlTZu3Kjy8nJNmDBBdXV1ZpspU6Zo9+7dysnJUU5Ojnbv3q3s7Ox2PV4AANBBGR1IUVGRIclYv369YRiGUV9fbyQnJxvPP/+82aa6utpwOBzGb3/7W8MwDKOkpMQIDg42Vq1aZbbJy8szAgICjJycHMMwDOPAgQOGJGPLli1mm82bNxuSjM8//7xFtblcLkOS4XK5rvg4AQDAeeN+scFI/9G7xoZ/Ffl82y39/e5QY4hcLpckKS4uTpJ05MgRFRQUaMyYMWYbu92uYcOGadOmTZKknTt3qqamxqtNamqqMjIyzDabN2+Ww+FQZmam2WbIkCFyOBxmm4u53W6VlpZ6vQAAQNfUYQKRYRiaM2eObrnlFmVkZEiSCgoKJElJSUlebZOSksx1BQUFCgkJUWxs7CXbJCYmNtpnYmKi2eZiixYtMscbORwOpaWlXdkBAgCADqvDBKKZM2dqz549+vOf/9xo3cUzWBqGcdlZLS9u01T7S21n/vz5crlc5uv48eMtOQwAANAJdYhANGvWLP3tb3/Thx9+qB49epjLk5OTJalRL05RUZHZa5ScnCyPxyOn03nJNoWFhY32e+rUqUa9T+fY7XZFR0d7vQAAQNfk10BkGIZmzpypt99+W+vWrVPv3r291vfu3VvJyclau3atuczj8Wj9+vUaOnSoJGnQoEEKDg72apOfn699+/aZbbKysuRyubRt2zazzdatW+Vyucw2AADAuoL8ufMZM2bojTfe0DvvvKOoqCizJ8jhcCgsLEw2m02zZ8/WwoUL1bdvX/Xt21cLFy5UeHi4pkyZYra97777NHfuXMXHxysuLk7z5s3TgAEDNGrUKElS//79NW7cOE2fPl3Lli2TJD3wwAOaMGGC+vXr55+DBwAAHYZfA9HSpUslScOHD/davnz5ck2bNk2S9MMf/lBVVVV65JFH5HQ6lZmZqffff19RUVFm+8WLFysoKEj33HOPqqqqdPvtt2vFihUKDAw026xcuVKPPvqoeTfapEmTtGTJkrY9QAAA0CnYDMMw/F1EZ1BaWiqHwyGXy8V4IgAAfGj8Lz/WwfxSvX7fTbq1bzefbrulv98dYlA1AACAPxGIAACA5RGIAABAh+DPQTwEIgAA4FeXnmq5fRCIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5fk1EC1atEjf+MY3FBUVpcTERE2ePFmHDh3yajNt2jTZbDav15AhQ7zauN1uzZo1SwkJCYqIiNCkSZN04sQJrzZOp1PZ2dlyOBxyOBzKzs5WSUlJWx8iAADoBPwaiNavX68ZM2Zoy5YtWrt2rWprazVmzBhVVFR4tRs3bpzy8/PN15o1a7zWz549W6tXr9aqVau0ceNGlZeXa8KECaqrqzPbTJkyRbt371ZOTo5ycnK0e/duZWdnt8txAgCAji3InzvPycnx+rx8+XIlJiZq586duu2228zldrtdycnJTW7D5XLp1Vdf1euvv65Ro0ZJkv70pz8pLS1NH3zwgcaOHauDBw8qJydHW7ZsUWZmpiTplVdeUVZWlg4dOqR+/fo12q7b7Zbb7TY/l5aWXvHxAgCAjqlDjSFyuVySpLi4OK/lH330kRITE3XNNddo+vTpKioqMtft3LlTNTU1GjNmjLksNTVVGRkZ2rRpkyRp8+bNcjgcZhiSpCFDhsjhcJhtLrZo0SLz8prD4VBaWprPjhMAAHQsHSYQGYahOXPm6JZbblFGRoa5fPz48Vq5cqXWrVunl156Sdu3b9fIkSPN3puCggKFhIQoNjbWa3tJSUkqKCgw2yQmJjbaZ2JiotnmYvPnz5fL5TJfx48f99WhAgCADsavl8wuNHPmTO3Zs0cbN270Wn7vvfea7zMyMjR48GClp6frvffe0ze/+c1mt2cYhmw2m/n5wvfNtbmQ3W6X3W5v7WEAAIBOqEP0EM2aNUt/+9vf9OGHH6pHjx6XbJuSkqL09HQdPnxYkpScnCyPxyOn0+nVrqioSElJSWabwsLCRts6deqU2QYAAFiXXwORYRiaOXOm3n77ba1bt069e/e+7HfOnDmj48ePKyUlRZI0aNAgBQcHa+3atWab/Px87du3T0OHDpUkZWVlyeVyadu2bWabrVu3yuVymW0AAIB1+fWS2YwZM/TGG2/onXfeUVRUlDmex+FwKCwsTOXl5VqwYIHuvvtupaSk6OjRo3ryySeVkJCgu+66y2x73333ae7cuYqPj1dcXJzmzZunAQMGmHed9e/fX+PGjdP06dO1bNkySdIDDzygCRMmNHmHGQAAsBa/BqKlS5dKkoYPH+61fPny5Zo2bZoCAwO1d+9evfbaayopKVFKSopGjBihN998U1FRUWb7xYsXKygoSPfcc4+qqqp0++23a8WKFQoMDDTbrFy5Uo8++qh5N9qkSZO0ZMmStj9IAADQ4dkMwzD8XURnUFpaKofDIZfLpejoaH+XAwBAl/Efv/xYB/JL9dr3b9Jt13Tz6bZb+vvdIQZVAwAA+BOBCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWB6BCAAAWJ5fA9HSpUs1cOBARUdHKzo6WllZWfr73/9urjcMQwsWLFBqaqrCwsI0fPhw7d+/32sbbrdbs2bNUkJCgiIiIjRp0iSdOHHCq43T6VR2drYcDoccDoeys7NVUlLSHocIAAA6Ab8Goh49euj555/Xjh07tGPHDo0cOVJ33nmnGXpefPFFvfzyy1qyZIm2b9+u5ORkjR49WmVlZeY2Zs+erdWrV2vVqlXauHGjysvLNWHCBNXV1ZltpkyZot27dysnJ0c5OTnavXu3srOz2/14AQBAB2V0MLGxscbvf/97o76+3khOTjaef/55c111dbXhcDiM3/72t4ZhGEZJSYkRHBxsrFq1ymyTl5dnBAQEGDk5OYZhGMaBAwcMScaWLVvMNps3bzYkGZ9//nmzdVRXVxsul8t8HT9+3JBkuFwuXx8yAACWNv4XG4z0H71rrD9U5PNtu1yuFv1+d5gxRHV1dVq1apUqKiqUlZWlI0eOqKCgQGPGjDHb2O12DRs2TJs2bZIk7dy5UzU1NV5tUlNTlZGRYbbZvHmzHA6HMjMzzTZDhgyRw+Ew2zRl0aJF5iU2h8OhtLQ0Xx8yAADoIPweiPbu3avIyEjZ7XY99NBDWr16ta699loVFBRIkpKSkrzaJyUlmesKCgoUEhKi2NjYS7ZJTExstN/ExESzTVPmz58vl8tlvo4fP35FxwkAADquIH8X0K9fP+3evVslJSV66623NHXqVK1fv95cb7PZvNobhtFo2cUubtNU+8ttx263y263t/QwAABAJ+b3HqKQkBD16dNHgwcP1qJFi3Tdddfpl7/8pZKTkyWpUS9OUVGR2WuUnJwsj8cjp9N5yTaFhYWN9nvq1KlGvU8AAMCa/B6ILmYYhtxut3r37q3k5GStXbvWXOfxeLR+/XoNHTpUkjRo0CAFBwd7tcnPz9e+ffvMNllZWXK5XNq2bZvZZuvWrXK5XGYbAABgbX69ZPbkk09q/PjxSktLU1lZmVatWqWPPvpIOTk5stlsmj17thYuXKi+ffuqb9++WrhwocLDwzVlyhRJksPh0H333ae5c+cqPj5ecXFxmjdvngYMGKBRo0ZJkvr3769x48Zp+vTpWrZsmSTpgQce0IQJE9SvXz+/HTsAAOg4/BqICgsLlZ2drfz8fDkcDg0cOFA5OTkaPXq0JOmHP/yhqqqq9Mgjj8jpdCozM1Pvv/++oqKizG0sXrxYQUFBuueee1RVVaXbb79dK1asUGBgoNlm5cqVevTRR8270SZNmqQlS5a078ECAIAmhQQFyB4UoIDLjBFuSzbDMAy/7b0TKS0tlcPhkMvlUnR0tL/LAQAALdDS3+8ON4YIAACgvRGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5RGIAACA5QX5u4DOwjAMSVJpaamfKwEAAC117nf73O94cwhELVRWViZJSktL83MlAACgtcrKyuRwOJpdbzMuF5kgSaqvr9fJkycVFRUlm83ms+2WlpYqLS1Nx48fV3R0tM+2i8Y41+2D89w+OM/tg/PcPtryPBuGobKyMqWmpiogoPmRQvQQtVBAQIB69OjRZtuPjo7mP7Z2wrluH5zn9sF5bh+c5/bRVuf5Uj1D5zCoGgAAWB6BCAAAWB6ByM/sdrueeeYZ2e12f5fS5XGu2wfnuX1wntsH57l9dITzzKBqAABgefQQAQAAyyMQAQAAyyMQAQAAyyMQAQAAyyMQ+dFzzz2noUOHKjw8XDExMU22yc3N1cSJExUREaGEhAQ9+uij8ng87VtoF7Rr1y6NHj1aMTExio+P1wMPPKDy8nJ/l9Xl/Otf/9Kdd96phIQERUdH6+abb9aHH37o77K6lI8++kg2m63J1/bt2/1dXpfz3nvvKTMzU2FhYUpISNA3v/lNf5fU5fTq1avRv+UnnniizfdLIPIjj8ejb3/723r44YebXF9XV6c77rhDFRUV2rhxo1atWqW33npLc+fObedKu5aTJ09q1KhR6tOnj7Zu3aqcnBzt379f06ZN83dpXc4dd9yh2tparVu3Tjt37tT111+vCRMmqKCgwN+ldRlDhw5Vfn6+1+v+++9Xr169NHjwYH+X16W89dZbys7O1n/+53/qs88+0yeffKIpU6b4u6wu6dlnn/X6N/3000+3/U4N+N3y5csNh8PRaPmaNWuMgIAAIy8vz1z25z//2bDb7YbL5WrHCruWZcuWGYmJiUZdXZ257NNPPzUkGYcPH/ZjZV3LqVOnDEnGhg0bzGWlpaWGJOODDz7wY2Vdm8fjMRITE41nn33W36V0KTU1NUb37t2N3//+9/4upctLT083Fi9e3O77pYeoA9u8ebMyMjKUmppqLhs7dqzcbrd27tzpx8o6N7fbrZCQEK+H/IWFhUmSNm7c6K+yupz4+Hj1799fr732mioqKlRbW6tly5YpKSlJgwYN8nd5Xdbf/vY3nT59mh5PH9u1a5fy8vIUEBCgG264QSkpKRo/frz279/v79K6pBdeeEHx8fG6/vrr9dxzz7XLUBECUQdWUFCgpKQkr2WxsbEKCQnhksMVGDlypAoKCvTzn/9cHo9HTqdTTz75pCQpPz/fz9V1HTabTWvXrtWnn36qqKgohYaGavHixcrJyWl2zByu3KuvvqqxY8cqLS3N36V0KV9++aUkacGCBXr66af17rvvKjY2VsOGDVNxcbGfq+taHnvsMa1atUoffvihZs6cqV/84hd65JFH2ny/BCIfW7BgQbMDHM+9duzY0eLt2Wy2RssMw2hyudW19Nx//etf1x//+Ee99NJLCg8PV3Jysq666iolJSUpMDDQ34fR4bX0PBuGoUceeUSJiYn6+OOPtW3bNt15552aMGECwbMFvsr/lpw4cUL/+Mc/dN999/mp6s6npee5vr5ekvTUU0/p7rvv1qBBg7R8+XLZbDb95S9/8fNRdHyt+ff8+OOPa9iwYRo4cKDuv/9+/fa3v9Wrr76qM2fOtGmNPLrDx06fPq3Tp09fsk2vXr0UGhpqfl6xYoVmz56tkpISr3Y/+clP9M477+izzz4zlzmdTsXFxWndunUaMWKET2vv7L7KuS8sLFRERIRsNpuio6O1atUqffvb327rUju1lp7nTz75RGPGjJHT6VR0dLS5rm/fvrrvvvva5a6Rzuyr/Hv+6U9/ql//+tfKy8tTcHBwW5fYJbT0PG/evFkjR47Uxx9/rFtuucVcl5mZqVGjRum5555r61I7ta/y7/mcvLw89ejRQ1u2bFFmZmZblaigNtuyRSUkJCghIcEn28rKytJzzz2n/Px8paSkSJLef/992e12xmA04auc+3OXJP/whz8oNDRUo0ePbovSupSWnufKykpJ8hqrde7zuf+3jea19t+zYRhavny5vve97xGGWqGl53nQoEGy2+06dOiQGYhqamp09OhRpaent3WZnd6V/DZ++umnkmT+DrYVApEf5ebmqri4WLm5uaqrq9Pu3bslSX369FFkZKTGjBmja6+9VtnZ2fr5z3+u4uJizZs3T9OnT/f6f9xovSVLlmjo0KGKjIzU2rVr9YMf/EDPP/88Y1t8KCsrS7GxsZo6dap+8pOfKCwsTK+88oqOHDmiO+64w9/ldTnr1q3TkSNHuFzWRqKjo/XQQw/pmWeeUVpamtLT0/Xzn/9ckuhV9qHNmzdry5YtGjFihBwOh7Zv367HH39ckyZNUs+ePdt25+1+XxtMU6dONSQ1en344Ydmm2PHjhl33HGHERYWZsTFxRkzZ840qqur/Vd0F5GdnW3ExcUZISEhxsCBA43XXnvN3yV1Sdu3bzfGjBljxMXFGVFRUcaQIUOMNWvW+LusLuk73/mOMXToUH+X0aV5PB5j7ty5RmJiohEVFWWMGjXK2Ldvn7/L6lJ27txpZGZmGg6HwwgNDTX69etnPPPMM0ZFRUWb75sxRAAAwPK4ywwAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAOoAzZ84oMTFRR48e9Vru8Xg0d+5czZs3Tx6Px6f7/Na3vqWXX37Zp9sEOisCEQDZbLZLvqZNm+bvEtvM8OHDNXv2bH+XoUWLFmnixInq1auX1/I333xTN954o26++Wa9/vrrLd5eQUGBZs2apauuukp2u11paWmaOHGi/vnPf5ptfvKTn+i5555TaWmprw4D6LSC/F0AAP/Lz88337/55pv6yU9+okOHDpnLwsLC/FHWV+bxeBQSEtJp9llVVaVXX31Va9asabSuvr5ewcHBqqurU319fYu2d/ToUd18882KiYnRiy++qIEDB6qmpkb/+Mc/NGPGDH3++eeSpIEDB6pXr15auXKlHn744a9UO9BlGABwgeXLlxsOh6PR8vr6euOFF14wevfubYSGhhoDBw40/vKXv3i1GTZsmDFz5kzjscceM2JiYozExERj2bJlRnl5uTFt2jQjMjLSuOqqq4w1a9Z4fWfGjBnGjBkzDIfDYcTFxRlPPfWUUV9f3+J9n9vG448/bsTHxxu33XabYRiG8fe//924+eabze3ecccdxhdffGF+b+rUqYYkr9eRI0eM9PR0Y/HixV7Hdt111xnPPPPMZffZkvN0sbfeestISEhocl11dbXx2GOPGbNnzzaqq6svuZ1zxo8fb3Tv3t0oLy9vtM7pdHp9XrBggXHrrbe2aLtAV8YlMwAt8vTTT2v58uVaunSp9u/fr8cff1zf/e53tX79eq92f/zjH5WQkKBt27Zp1qxZevjhh/Xtb39bQ4cO1a5duzR27FhlZ2ersrLS6ztBQUHaunWrfvWrX2nx4sX6/e9/36p9n9vGJ598omXLlkmSKioqNGfOHG3fvl3//Oc/FRAQoLvuusvsafnlL3+prKwsTZ8+Xfn5+crPz1daWlqLz0lT+2zpebrQhg0bNHjw4CbX2e12/eIXv9DixYtlt9svW1NxcbFycnI0Y8YMRURENFofExPj9fmmm27Stm3b5Ha7L7ttoEvzdyID0LE01UNUXl5uhIaGGps2bfJaft999xnf+c53zM/Dhg0zbrnlFvNzbW2tERERYWRnZ5vL8vPzDUnG5s2bze/079/fq0foRz/6kdG/f/8W73vYsGHG9ddff9ljKyoqMiQZe/fu9ar5scce82rX0h6ii/fZ0vN0sTvvvNP4/ve/f9n6W2Lr1q2GJOPtt99uUfvPPvvMkGQcPXrUJ/sHOivGEAG4rAMHDqi6ulqjR4/2Wu7xeHTDDTd4LRs4cKD5PjAwUPHx8RowYIC5LCkpSZJUVFRkLhsyZIhsNpv5OSsrSy+99JLq6upavO+melj+/e9/68c//rG2bNmi06dPmz1Dubm5ysjIaPHxN+fifbbmPF2oqqpKoaGhV1yPJBmGIUle5/NSzo0Pu7DHDrAiAhGAyzoXJN577z11797da93Fl3GCg4O9PttsNq9l536oWzpAuKX7bury0MSJE5WWlqZXXnlFqampqq+vV0ZGxmVvXw8ICDCDxTk1NTWN2l28z9acpwslJCTI6XResqaW6tu3r2w2mw4ePKjJkydftn1xcbEkqVu3bj7ZP9BZEYgAXNa1114ru92u3NxcDRs2zOfb37JlS6PPffv2VWBg4Ffe95kzZ3Tw4EEtW7ZMt956qyRp48aNjdqFhISorq7Oa1m3bt287rwrLS3VkSNHLrvPr1rrDTfcoD/96U8tbn8pcXFxGjt2rH7zm9/o0UcfbRTaSkpKvMYR7du3Tz169FBCQoJP9g90VgQiAJcVFRWlefPm6fHHH1d9fb1uueUWlZaWatOmTYqMjNTUqVOvaPvHjx/XnDlz9OCDD2rXrl369a9/rZdeeumK9h0bG6v4+Hj97ne/U0pKinJzc/XEE080aterVy9t3bpVR48eVWRkpOLi4jRy5EitWLFCEydOVGxsrH784x8rMDCwzc7T2LFjNX/+fDmdTsXGxrbizDXtv//7vzV06FDddNNNevbZZzVw4EDV1tZq7dq1Wrp0qQ4ePGi2/fjjjzVmzJgr3ifQ2RGIALTIT3/6UyUmJmrRokX68ssvFRMToxtvvFFPPvnkFW/7e9/7nqqqqnTTTTcpMDBQs2bN0gMPPHBF+w4ICNCqVav06KOPKiMjQ/369dOvfvUrDR8+3KvdvHnzNHXqVF177bWqqqrSkSNHNH/+fH355ZeaMGGCHA6HfvrTn7aoh+ir1jpgwAANHjxY//M//6MHH3ywRfu5lN69e2vXrl167rnnNHfuXOXn56tbt24aNGiQli5dararrq7W6tWr9Y9//OOK9wl0djbj4gvlANCOhg8fruuvv16/+MUv/F2KX61Zs0bz5s3Tvn37FBDQPjOi/OY3v9E777yj999/v132B3Rk9BABQAfwH//xHzp8+LDy8vJaNRfSlQgODtavf/3rdtkX0NERiACgg3jsscfadX8XXpYErI5LZgAAwPJ4dAcAALA8AhEAALA8AhEAALA8AhEAALA8AhEAALA8AhEAALA8AhEAALA8AhEAALA8AhEAALA8AhEAALC8/x/cRKDucsLwWQAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "model = SimpleGlacier(z, T0)\n", "\n", @@ -840,61 +674,22 @@ }, { "cell_type": "code", - "execution_count": 54, - "id": "42bbf2f2-3791-4e8d-b4dc-066d3d50a5d1", + "execution_count": null, + "id": "dccba120-feb5-4ae6-b726-99146df0700f", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0.05475818525543331 years.\n", - "54.81294344068874 years.\n", - "109.57112869612205 years.\n", - "164.32931395155535 years.\n", - "219.08749920698867 years.\n", - "273.84568446242196 years.\n", - "328.6038697178553 years.\n", - "383.3620549732886 years.\n", - "438.1202402287219 years.\n", - "492.87842548415523 years.\n", - "547.6366107395885 years.\n", - "602.3947959950218 years.\n", - "657.1529812504551 years.\n", - "711.9111665058884 years.\n", - "766.6693517613218 years.\n", - "821.4275370167551 years.\n", - "876.1857222721884 years.\n", - "930.9439075276217 years.\n", - "985.7020927830549 years.\n", - "1040.4602780384882 years.\n", - "1095.2184632939216 years.\n", - "1149.9766485493549 years.\n", - "1204.7348338047882 years.\n", - "1259.4930190602215 years.\n", - "1314.2512043156548 years.\n", - "1369.0093895710881 years.\n", - "1423.7675748265215 years.\n", - "1478.5257600819548 years.\n", - "1533.283945337388 years.\n", - "1588.0421305928214 years.\n" - ] - }, - { - "data": { - "image/png": "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1GW0KovFIsyfP1/QarWCSqUSRo4cKRw/flzqslrcwYMHhbi4OEGtVgvu7u5Cjx49hNdff10oLy+XurRWl56e3i63Bzh69KgwfPhwQaPRCEqlUoiIiBCefPJJITs7W+rSWtzq1asb/I5tbvThGiUiIiKiRvCqNyIiIqJGMCgRERERNYJBiYiIiKgRDEpEREREjWBQIiIiImoEgxIRERFRIxiUiIiIiBrBoERERETUCAYlIiIiokYwKBERERE1gkGJiMgJFBUVQavVIiMjw+64xWLB/PnzsWDBAlgslhb9zAcffBDvvvtui74nUXvDoEREkMlk131MmzZN6hJbzbBhwzB37lypy8DSpUsxYcIERERE2B3fuHEjbr/9dtx5551Yt25dk99Pr9djzpw56NKlC5RKJcLCwjBhwgT8/PPPYpvXXnsNixcvhslkaqluELU7LlIXQETSy8vLE3/euHEjXnvtNaSlpYnHPDw8pCjrplksFri5ubWZz6yoqMBnn32GLVu21DtntVrh6uqKmpoaWK3WJr1fRkYG7rzzTvj6+uKtt95Cnz59UFVVha1bt+Lpp5/G6dOnAQB9+vRBREQE1q9fj6eeeuqmaidq9wQiojpWr14tqNXqesetVquwbNkyITIyUnB3dxf69OkjfPXVV3Zthg4dKsyePVt49tlnBV9fX0Gr1QqrVq0SysrKhGnTpgne3t5Cly5dhC1btti95umnnxaefvppQa1WCxqNRnjllVcEq9Xa5M+ufY/nnntO8Pf3F4YMGSIIgiD897//Fe68807xfe+55x7h3Llz4uumTp0qALB7pKenC+Hh4cLy5cvt+ta3b1/h9ddfv+FnNuXX6Vpff/21EBAQ0OC5yspK4dlnnxXmzp0rVFZWXvd9ao0bN04IDQ0VysrK6p0zGAx2zxctWiTcddddTXpfoo6IU29E1CSvvvoqVq9ejZUrV+LEiRN47rnn8Oijj2LXrl127T7//HMEBARg//79mDNnDp566ik89NBDSEhIwKFDhzBmzBgkJibi8uXLdq9xcXHBvn378P7772P58uX49NNPm/XZte/x22+/YdWqVQCA8vJyzJs3DwcOHMDPP/8MuVyO++67TxyZ+cc//oH4+HjMmDEDeXl5yMvLQ1hYWJN/TRr6zKb+OtW1e/duDBgwoMFzSqUS7733HpYvXw6lUnnDmoqLi5GUlISnn34aXl5e9c77+vraPR84cCD2798Ps9l8w/cm6pCkTmpE5FwaGlEqKysT3N3dheTkZLvj06dPFx555BHx+dChQ4XBgweLz6urqwUvLy8hMTFRPJaXlycAEPbu3Su+pmfPnnYjSC+++KLQs2fPJn/20KFDhX79+t2wbwUFBQIA4dixY3Y1P/vss3btmjqidO1nNvXX6Vr33nuv8Kc//emG9TfFvn37BADCN99806T2R44cEQAIGRkZLfL5RO0N1ygR0Q2dPHkSlZWVGDVqlN1xi8WC/v372x3r06eP+LNCoYC/vz9iYmLEYzqdDgBQUFAgHhs0aBBkMpn4PD4+Hu+88w5qamqa/NkNjcicP38ef/7zn5GSkoJLly6JI0mZmZmIjo5ucv8bc+1nNufXqa6Kigq4u7vfcj0AIAgCANj9el5P7fqzuiN8RHQVgxIR3VBtwPjxxx8RGhpqd+7a6SBXV1e75zKZzO5Y7Rd4UxcmN/WzG5pmmjBhAsLCwvDJJ58gJCQEVqsV0dHRN7zMXi6Xi4GjVlVVVb12135mc36d6goICIDBYLhuTU0VFRUFmUyGU6dOYdKkSTdsX1xcDAAIDAxskc8nam8YlIjohnr16gWlUonMzEwMHTq0xd8/JSWl3vOoqCgoFIqb/uyioiKcOnUKq1atwl133QUA2LNnT712bm5uqKmpsTsWGBhodyWgyWRCenr6DT/zZmvt378//v3vfze5/fVoNBqMGTMGH374IZ555pl6Ya6kpMRundLx48fRqVMnBAQEtMjnE7U3DEpEdEMqlQoLFizAc889B6vVisGDB8NkMiE5ORne3t6YOnXqLb1/VlYW5s2bhyeeeAKHDh3CBx98gHfeeeeWPtvPzw/+/v74+OOPERwcjMzMTLz00kv12kVERGDfvn3IyMiAt7c3NBoNRowYgTVr1mDChAnw8/PDn//8ZygUilb7dRozZgwWLlwIg8EAPz+/ZvzKNeyf//wnEhISMHDgQLzxxhvo06cPqqursX37dqxcuRKnTp0S2/76668YPXr0LX8mUXvFoERETfLmm29Cq9Vi6dKluHDhAnx9fXH77bfj5ZdfvuX3fuyxx1BRUYGBAwdCoVBgzpw5mDlz5i19tlwux4YNG/DMM88gOjoaPXr0wPvvv49hw4bZtVuwYAGmTp2KXr16oaKiAunp6Vi4cCEuXLiA8ePHQ61W480332zSiNLN1hoTE4MBAwbgP//5D5544okmfc71REZG4tChQ1i8eDHmz5+PvLw8BAYGIjY2FitXrhTbVVZWYtOmTdi6destfyZReyUTrp2IJyJyoGHDhqFfv3547733pC5FUlu2bMGCBQtw/PhxyOWO2bnlww8/xHfffYdt27Y55POI2iKOKBEROYE//OEPOHv2LHJycpq1l9OtcHV1xQcffOCQzyJqqxiUiIicxLPPPuvQz6s7vUlEDePUGxEREVEjeAsTIiIiokYwKBERERE1gkGJiIiIqBEMSkRERESNYFAiIiIiagSDEhEREVEjGJSIiIiIGsGgRERERNQIBiUiIiKiRjAoERERETXi/wE3vODiQm76UAAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], + "source": [ + "# Initialize your model with a new bottom boundary condition\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4cc607e6-10bb-4dd5-9994-b3076be2a093", + "metadata": {}, + "outputs": [], "source": [ - "model = SimpleGlacier(z, T0)\n", - "model.basal_heat_flux = 0.01\n", - "\n", "dt = 60 * 60 * 24 * 20\n", "\n", "for i in range(30000): \n", @@ -910,6 +705,112 @@ "plt.show()" ] }, + { + "cell_type": "markdown", + "id": "038ac06d-9307-4717-987a-5dece0a6b682", + "metadata": {}, + "source": [ + "### Spoilers below!" + ] + }, + { + "cell_type": "markdown", + "id": "038be991-e91b-488f-b423-f9ad2d833d8b", + "metadata": {}, + "source": [ + "This is one example of how you could choose to write this class." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a74ed31d-6be6-40cb-a018-89830b53b923", + "metadata": { + "jupyter": { + "source_hidden": true + } + }, + "outputs": [], + "source": [ + "class SimpleGlacier:\n", + " \"\"\"Models the temperature profile with a glacier.\n", + " \n", + " This model is based off of: \n", + " The Physics of Glaciers (Cuffey and Paterson, 2010).\n", + " Lecture notes from Andy Aschwanden (McCarthy school, summer 2012).\n", + "\n", + " Attributes:\n", + " z: an array of z-coordinates\n", + " temperature: an array representing the temperature profile with depth\n", + " \"\"\"\n", + "\n", + " def __init__(self, z: np.ndarray, initial_temperature: np.ndarray):\n", + " \"\"\"Initialize the model with arrays of z-coordinates and initial temperature profile.\"\"\"\n", + " self.z = z\n", + " self.temperature = initial_temperature\n", + "\n", + " # We probably want to calculate dz --> try using np.gradient\n", + " self.dz = np.gradient(self.z)\n", + " # Note: I didn't realize this when I originally wrote the class, but we won't need dz\n", + " # Want to know why? Check out the documentation for np.gradient -> https://numpy.org/doc/stable/reference/generated/numpy.gradient.html\n", + " \n", + " # We'll need attributes for rho, c, and k\n", + " # You could also store info about boundary conditions at this point, if you want\n", + " self.rho = 917\n", + " self.c = 2093\n", + " self.k = 2.1\n", + "\n", + " # Let's store boundary conditions too\n", + " self.surface_temperature = -10.0\n", + " self.basal_heat_flux = 0.0\n", + " \n", + " # Maybe we should go ahead and calculate diffusivity right away?\n", + " self.kappa = self.calc_diffusivity()\n", + " \n", + " # Let's keep track of the elapsed time\n", + " self.time_elapsed = 0.0\n", + "\n", + " def calc_diffusivity(self) -> float:\n", + " \"\"\"From above, kappa = k / (rho * c).\"\"\"\n", + " return self.k / (self.rho * self.c)\n", + "\n", + " def calc_heat_flux(self) -> np.ndarray:\n", + " \"\"\"The heat flux is -kappa * dT / dz.\"\"\"\n", + " \n", + " # How should we calculate the difference in temperature with depth? (hint: see dz, above)\n", + " temperature_gradient = np.gradient(self.temperature, self.z)\n", + "\n", + " # Are dT and dz the same size? Are they the same size as z?\n", + " assert temperature_gradient.shape == self.dz.shape == self.z.shape\n", + "\n", + " # Don't forget to apply boundary conditions! The heat flux at the bed should be zero, for now.\n", + " temperature_gradient[-1] = self.basal_heat_flux\n", + "\n", + " return -self.kappa * temperature_gradient\n", + " \n", + " def calc_divergence(self) -> np.ndarray:\n", + " \"\"\"In 1D, divergence is just the derivative. yay!\"\"\"\n", + " heat_flux = self.calc_heat_flux()\n", + " \n", + " flux_divergence = np.gradient(heat_flux, self.z)\n", + " \n", + " return flux_divergence\n", + " \n", + " def run_one_step(self, dt: float):\n", + " \"\"\"Advance the model by one step of size dt.\"\"\"\n", + " flux_divergence = self.calc_divergence()\n", + "\n", + " # updated temperature = current temperature - the divergence * dt\n", + " updated_temperature = self.temperature - flux_divergence * dt\n", + "\n", + " # Don't forget to apply boundary conditions! The temperature at the surface is equal to a fixed value.\n", + " updated_temperature[0] = self.surface_temperature\n", + "\n", + " self.temperature = updated_temperature\n", + "\n", + " self.time_elapsed += dt" + ] + }, { "cell_type": "markdown", "id": "2d0e9161-1824-4be5-8f17-a3ea322e01f6", @@ -938,21 +839,10 @@ }, { "cell_type": "code", - "execution_count": 542, + "execution_count": null, "id": "7de68364-01b1-4c34-8c43-4392411f5a4a", "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# Replace test_array with your results\n", "test_array = np.random.random((10, 10))\n", @@ -994,7 +884,7 @@ }, { "cell_type": "code", - "execution_count": 373, + "execution_count": null, "id": "d54d9620-8be3-44d5-846f-cf58b616030b", "metadata": {}, "outputs": [], @@ -1019,7 +909,7 @@ }, { "cell_type": "code", - "execution_count": 548, + "execution_count": null, "id": "9bdc456b-4425-48ef-8b5f-aa9a42a33abe", "metadata": {}, "outputs": [], @@ -1036,21 +926,10 @@ }, { "cell_type": "code", - "execution_count": 547, + "execution_count": null, "id": "df9ab5b5-a885-4219-b49f-32cbf7dfee25", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Help on function run_one_step in module __main__:\n", - "\n", - "run_one_step(self)\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "help(DiffusionChild.run_one_step)" ] @@ -1065,22 +944,10 @@ }, { "cell_type": "code", - "execution_count": 549, + "execution_count": null, "id": "1474651c-a28b-4c5a-92ed-271be7b98b9a", "metadata": {}, - "outputs": [ - { - "ename": "AttributeError", - "evalue": "type object 'DiffusionModel1D' has no attribute 'no_parents_allowed'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[549], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m help(\u001b[43mDiffusionModel1D\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mno_parents_allowed\u001b[49m)\n", - "\u001b[0;31mAttributeError\u001b[0m: type object 'DiffusionModel1D' has no attribute 'no_parents_allowed'" - ] - } - ], + "outputs": [], "source": [ "help(DiffusionModel1D.no_parents_allowed)" ] From 8bf7cdb2fcac5295755e6c6ad7c7cdd99fd9855a Mon Sep 17 00:00:00 2001 From: Mark Piper Date: Fri, 9 Aug 2024 14:11:46 -0600 Subject: [PATCH 5/5] Make pretty --- lessons/python/yet_another_oop.ipynb | 51 ++++++++++++++-------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/lessons/python/yet_another_oop.ipynb b/lessons/python/yet_another_oop.ipynb index 2a8d720..6ed6db2 100644 --- a/lessons/python/yet_another_oop.ipynb +++ b/lessons/python/yet_another_oop.ipynb @@ -540,7 +540,7 @@ " # Note: I didn't realize this when I originally wrote the class, but we won't actually need dz\n", " # Want to know why? Check out the documentation for np.gradient -> https://numpy.org/doc/stable/reference/generated/numpy.gradient.html\n", " # (What does the second argument to np.gradient do?)\n", - " \n", + "\n", " # We'll need attributes for rho, c, and k\n", " # You could also store info about boundary conditions at this point, if you want\n", " self.rho = 917\n", @@ -548,9 +548,9 @@ " self.k = 2.1\n", "\n", " # Let's store boundary conditions too\n", - " \n", + "\n", " # Maybe we should go ahead and calculate diffusivity right away?\n", - " \n", + "\n", " # Let's keep track of the elapsed time\n", "\n", " def calc_diffusivity(self) -> float:\n", @@ -559,7 +559,7 @@ "\n", " def calc_heat_flux(self) -> np.ndarray:\n", " \"\"\"The heat flux is -kappa * dT / dz.\"\"\"\n", - " \n", + "\n", " # How should we calculate the difference in temperature with depth? (hint: see dz, above)\n", "\n", " # Are dT and dz the same size? Are they the same size as z?\n", @@ -634,16 +634,16 @@ "\n", "dt = 60 * 60 * 24 * 20\n", "\n", - "for i in range(30000): \n", + "for i in range(30000):\n", " model.run_one_step(dt)\n", "\n", " if i % 1000 == 0:\n", - " print(f'{model.time_elapsed / 31556926} years.')\n", + " print(f\"{model.time_elapsed / 31556926} years.\")\n", "\n", "plt.plot(model.temperature, model.z)\n", - "plt.xlabel('Temperature ($^\\circ$ C)')\n", - "plt.ylabel('Depth (m)')\n", - "plt.gca().invert_yaxis() # This forces matplotlib to invert the y-axis\n", + "plt.xlabel(r\"Temperature ($^\\circ$ C)\")\n", + "plt.ylabel(\"Depth (m)\")\n", + "plt.gca().invert_yaxis() # This forces matplotlib to invert the y-axis\n", "plt.show()" ] }, @@ -662,8 +662,7 @@ "metadata": {}, "outputs": [], "source": [ - "# Initialize your model with a new bottom boundary condition\n", - "\n" + "# Initialize your model with a new bottom boundary condition" ] }, { @@ -675,16 +674,16 @@ "source": [ "dt = 60 * 60 * 24 * 20\n", "\n", - "for i in range(30000): \n", + "for i in range(30000):\n", " model.run_one_step(dt)\n", "\n", " if i % 1000 == 0:\n", - " print(f'{model.time_elapsed / 31556926} years.')\n", + " print(f\"{model.time_elapsed / 31556926} years.\")\n", "\n", "plt.plot(model.temperature, model.z)\n", - "plt.xlabel('Temperature ($^\\circ$ C)')\n", - "plt.ylabel('Depth (m)')\n", - "plt.gca().invert_yaxis() # This forces matplotlib to invert the y-axis\n", + "plt.xlabel(r\"Temperature ($^\\circ$ C)\")\n", + "plt.ylabel(\"Depth (m)\")\n", + "plt.gca().invert_yaxis() # This forces matplotlib to invert the y-axis\n", "plt.show()" ] }, @@ -717,8 +716,8 @@ "source": [ "class SimpleGlacier:\n", " \"\"\"Models the temperature profile with a glacier.\n", - " \n", - " This model is based off of: \n", + "\n", + " This model is based off of:\n", " The Physics of Glaciers (Cuffey and Paterson, 2010).\n", " Lecture notes from Andy Aschwanden (McCarthy school, summer 2012).\n", "\n", @@ -736,7 +735,7 @@ " self.dz = np.gradient(self.z)\n", " # Note: I didn't realize this when I originally wrote the class, but we won't need dz\n", " # Want to know why? Check out the documentation for np.gradient -> https://numpy.org/doc/stable/reference/generated/numpy.gradient.html\n", - " \n", + "\n", " # We'll need attributes for rho, c, and k\n", " # You could also store info about boundary conditions at this point, if you want\n", " self.rho = 917\n", @@ -746,10 +745,10 @@ " # Let's store boundary conditions too\n", " self.surface_temperature = -10.0\n", " self.basal_heat_flux = 0.0\n", - " \n", + "\n", " # Maybe we should go ahead and calculate diffusivity right away?\n", " self.kappa = self.calc_diffusivity()\n", - " \n", + "\n", " # Let's keep track of the elapsed time\n", " self.time_elapsed = 0.0\n", "\n", @@ -759,7 +758,7 @@ "\n", " def calc_heat_flux(self) -> np.ndarray:\n", " \"\"\"The heat flux is -kappa * dT / dz.\"\"\"\n", - " \n", + "\n", " # How should we calculate the difference in temperature with depth? (hint: see dz, above)\n", " temperature_gradient = np.gradient(self.temperature, self.z)\n", "\n", @@ -770,15 +769,15 @@ " temperature_gradient[-1] = self.basal_heat_flux\n", "\n", " return -self.kappa * temperature_gradient\n", - " \n", + "\n", " def calc_divergence(self) -> np.ndarray:\n", " \"\"\"In 1D, divergence is just the derivative. yay!\"\"\"\n", " heat_flux = self.calc_heat_flux()\n", - " \n", + "\n", " flux_divergence = np.gradient(heat_flux, self.z)\n", - " \n", + "\n", " return flux_divergence\n", - " \n", + "\n", " def run_one_step(self, dt: float):\n", " \"\"\"Advance the model by one step of size dt.\"\"\"\n", " flux_divergence = self.calc_divergence()\n",