 who are new to LandLab, I'll just do a quick introduction with a few slides here to give you a flavor of what this is. So LandLab is basically a CSDMS-oriented project that is designed to make a little bit easier to build numerical models of one sort or another. And maybe the general term I'm looking for, since many things are grid-based, maybe the term I'm looking for numerical solutions to differential equations, though actually LandLab is a little bit broader than that. But at any rate, it's a explicitly Python language programming library or toolkit. And it's part of the sort of CSDMS philosophy of let's make our scientific productivity more efficient by sharing interoperable components that we can reuse so that as researchers we're free to spend more of our time thinking about the difficult conceptual questions and less time monkeying around with software headaches. So the vision behind LandLab, it was inspired in part by an observation that across a lot of different areas of science, areas that touch on Earth's surface in one fashion or another, there's a lot of very similar computational work that goes on, but it goes on in silos. And what I mean by this is illustrated in this diagram. So these are images from a half a dozen different papers in different subfields within, let's say, the geoscience, environmental science, planetary science sphere. And they all involve what you might think of as distributed or grid based numerical models. So in the upper left is a watershed hydrology model showing depth to bedrock. In the upper middle is a kind of field scale soil erosion model. So kind of in up Derek's alley, so to speak. On the upper right is a numerical simulation of glaciation, as it might have looked in the last ice age on the Sierra and Bottas. So the glaciology community. The lower left is a landscape evolution model. In the lower middle is a planetary science model. This is a simulation of impact cratering and water erosion on a hypothetical early Mars. And then the last one, as you can see, is a volcano and it comes from the volcanology community, simulating lava flows down an active volcano flame. So each of these papers, it comes in a different journal. It's a different community or sub community. Probably most of these authors don't know one another, though a few do. And each of the authors of these papers had to solve many of the same problems. So they all needed to set up some kind of a computational grid on which to do their calculations. They all had to think about tracking geophysical flows across that terrain. Lava or ice or soil or anything else. They all had to think about all the normal headaches you do when you write a program like this. You had to think about inputs and outputs and what format are you going to use and how you can get parameters into your model and how are you going to get output and how are you going to visualize it and all these things. So there's a whole range of tasks that are being reinvented over and over by researchers in different fields. And so one thought was, gosh, wouldn't it be nice if there was some kind of a programming library that would take care of some of the common elements behind these things so you could jump to the interesting stuff more quickly. And that's what LandLab is intended in part to try and try and serve. So for LandLab, unlike other systems tools, we picked a language. We picked Python as the front end language. And at LandLab, it's really a programming library when it comes down to it. And it's designed to make it easier to create 2D numerical models and to modify them, to reuse existing bits and pieces and so on. And so it's really a companion to the CSD tool. It's called the Python modeling tool. LandLab has really three key elements that I'll highlight here. One is that it makes it easy to set up a simulation grid. So Python is or can be an object-oriented language. So it takes advantage of object-oriented capabilities to represent a grid as an object. The grids use flat arrays to represent data. And that means that the same data structure can be used for different grid types. So you're going to have a grid that's hexagons or squares or irregular elements. And there's various kinds of built-in functions for typical numerical operations, like calculating a gradient in some kind of variable. To give you a little bit of a flavor for what this means, and you'll see a live example in a second, I can create a grid in one line of code. So here's a line grid equals raster model grid shape equals 1016, one line of code that creates an object that represents a grid with 10 rows and 16 columns that looks like this. And a grid is just a piece of data that represents a grid composed of several different elements. There are nodes, which are the little point-like quantities. There are links, which are little line segments that connect adjacent pairs of nodes. And there are cells, which are little blocks of land, of course, that can contain some quantity of interest. Here's a couple of examples of different kinds of grids. Here's a similar line of code that creates a hexagon grid layout and an overall hexagonal layout or a rectangular layout of hexes. Here's an example of a type of grid that uses what irregular elements to make a radiationship. So that's the idea behind grids. The second sort of key thing is the idea of reusable components. So if you or I or somebody writes, let's say, a soil erosion model, and you want to combine that soil erosion model with something else like, I don't know, carbon production and transport or something like that, well, you don't want to have to reinvent the wheel by rewriting that soil erosion model. So Landlab provides the capability of taking a little model of sort of one process and encapsulating it as a reusable component. So the idea becomes, if one way to create a model with Landlab, if you already have the components written, you can create a model by writing a what's usually a relatively small script that creates a grid, creates the fields of data that populate that grid. So maybe it's water depth or it's wind speed or whatever and creates the components that you want to have in your model. And those things together with a little bit of scripting to create a time loop, let's say, create it, that's what your model is. So this little picture is meant to be a diagrammatic illustration of what it would really be a short Python script. So that's the idea of components. And currently Landlab has a a growing library of components for shallow water flow and soil creep and landsliding, as Christina mentioned, and a bunch of other things. And then the third thing is just, well, let's see, okay, there's a there's a two and a half thing. There's a cute cellular automaton package built into Landlab that's sort of fun to play with. Simply mention that in passing. But really, the third main thing is a set of utility functions that are built in that do things like read in the DEM if you're using digital typography or write out data in a standardized format that you can then read into some visualization package. There's a there's a way to have formatted parameter inputs from a file and a little bit of basic plotting. So that's that's really just that's a quick summary of what what Landlab is. And one quick example from an application we're going to revisit in a second together with Mesa is what if you have a scarf that's been created by some earthquakes, and you want to know how that scarf degrades and smooths off over time. A common approach is to use a diffusion metaphor where you assume that the rate of soil flow down slope depends on the slope angle. And to create a spatially distributed model like this, it's it's something that's been done many times, but it's you know, it's effort, it would take a fair amount of of time if you were going to start from scratch using let's say Fortran with no libraries or anything like that. In Landlab, the core of a model like that is as little as six lines long. So here's a six lines of Python code using Landlab functions that that create the little animation that you see there. So it's meant to make the the model building process a little more efficient and again to save us time so we can focus on the bigger part of conceptual issues. So you can you can find out more about Landlab from its homepage which is the first URL on this slide. What I'm going to do next is I'm going to switch over to a little notebook to illustrate a couple of really totally toy examples that I hacked together this week just to illustrate ways in which you can take an ABM built in Mesa and connect it with a little mini Landlab model. None of these examples are meant to be anything like as sophisticated as for example what Michael has done or what Moir and Dean, Don or what Mary and Moz are working on, but it's it's intended to show a pathway to connect an agent-based model with a Landlab component. So as hopefully everybody has seen there's a all the stuff that I'm going to show is on the little GitHub site that I built for this workshop so if you want to download and follow along on the notebooks you can do so. I'll switch over now to a browser let's take a look at that while I'm doing that if anybody has any questions I'm happy to answer them. Greg if we wanted to follow along I mean I can open the Jupiter notebook but how would I actually get your files and things into it? Well let's see so you would you'd need an installation of the tools so Landlab I've got Landlab but I've got Landlab already put into a an Anaconda environment. Perfect then you need Mesa which is also it's PIP or Honda and then you can simply clone this repository from the clone or download button here. Okay all right well I know you know how to do that maybe not everybody but that should just work if you've installed everything hopefully the notebooks will just be there and work. I should be able to double well I I don't want to double click those because so the issue is I'm on I'm on a computer where the default Python is Python 2 that's why I make an Anaconda environment with Python 3 in it. Yeah well I think that's okay because if you if you just launch Jupiter from the environment. Yeah that's what you need to do launch launch the notebook from within your environment then I think you can create a Python 3 then it should work because these these do need to be Python 3. All right so what I'm going to start with this wolf sheep thing and those of you who know NetLogo know that one of the sort of canonical examples is this wolf sheep grass predation model so you have this grassy landscape that's populated by sheep which eat the grass and wolves that eat the sheep the more energy the sheep get from the grass the faster they can reproduce and the wolf get wolves get their energy from eating the sheep and if there's too few sheep the wolves eat them all and starve if there's too little grass the sheep starve if there's no wolves the sheep can explode in population and all kinds of interesting dynamics come out of it and Mesa has as one of their examples an implementation of the wolf sheep grass model so what I've done here is to make a little notebook so I'll move to over here I can't find this so I basically took the Mesa's implementation of wolf sheep grass and added it to just download it so it's it's in this collection if you clone the repo you'll get it too and I've tried to combine it with a little soil erosion model so the grass influences soil erosion and the soil erosion is influenced or the the sheep are influenced by the grass and therefore they influence the grass and influence soil erosion etc so there's a feedback so I'll just walk through this notebook quickly to get a flavor about what I've learned about Mesa and initially just running the wolf sheep grass model in this Jupiter notebook so Mesa provides a nice gooey you can visualize animations I haven't tried to make that work in a notebook so this is going to be pretty bare bones but we'll step through it so the idea behind a Mesa ABM is you create two kinds of class you have a model class in this case a wolf sheep model and you have one or more agents each of which has its own class and so they've created three classes one for grass one for wolves one for sheep I'm simply going to import the grass patch class because that's the only one I need to actually modify so in this line I'm going to instantiate a wolf sheep model and with the grass option turned on then this is a little bit of code to be able to visualize a map of the grass cover and let's see so I'm going to run my wolf sheep model for 25 steps and plot the result in grass cover okay there it is yellow is it should be green really I'm not using a good color map but hopefully you get the idea yellow is rich thick fully grown grass and dark blue is the grasses in bad shape or missing so okay so all that demonstrates is that it's possible once there's been an ABM written in Mesa to import it and run it so then we can try okay well what if we couple this one way we take a map like this and we will use a diffusion metaphor model for soil erosion not the most sophisticated model in the world admittedly but I'm using it here for its simplicity and I'm simply going to say that alongside the fact that the soil flux depends on the slope angle I'm going to say it depends on the slope angle and the grass cover and that it's going to be 100 times more flux where the grass is missing right so thinking that if you've ever seen like a construction site right after a rainstorm where all the veg has been taken away and you get all kinds of relaying and little alluvial fans and things like that you get a sense that you know grass really matters in holding together the soil so that's all we're going to try and do and I'm not going to go through every single line of code here but I want to give you a little bit of the gist about how this can work again trying to get it get the point at least my experience so far that coupling a land lab thing with the Mesa thing is pretty easy so I'm going to instantiate a new wolf sheep bottle I'm going to run it for just three steps so the sheep munch on the grass a little bit I'll generate a grass map and then I'm going to use that grass map to calculate the soil transport coefficient and then use that to evolve a hill slope for some amount of time I think I'm doing it for a hundred years or something okay so there's my grass map that I've evolved now I'm going to simply take that as a static one-way input and then the next step I'm going to import some stuff I need for land lab I need a grid so I'll use a raster grid I need a linear diffuser that's the component that calculates soil flow proportional to slope angle or slope gradient and a little function to display grids those are the inputs so in this long block of code what I'm going to do is first I'll create a grid that's this line here then I'm going to create a bunch of fields these are the arrays of data that are going to be connected to my grid so I'll have an elevation field and my elevation will slope up to the north at 10 gradient I will put walls on my on three sides of my landscape so everything flows off to the south I will remember the starting elevation so I can calculate the total cumulative erosion at the end I'll make a field for my creep coefficient so this is where the grass comes in and I'm going to have two possible creep rates a slow one and a fast one a slow one for grass and on the fast one for bear so these two lines here are where I take my creep coefficient array and I say okay wherever the grass has been removed or damaged that's gm grass map equals one I'm going to say that's fast and wherever the grass is in good shape that's gm equals two I'm going to say that's slow then I instantiate my component my linear diffuser component give it my creep coefficient array as it's transport coefficient I'll calculate a reasonable time step size and I'm ready to roll so that's all the all the setup so this next little block of code I'm going to have 50 iterations of two years each to calculate 100 years worth of soil erosion in a partly grassy partly bare landscape where the grass and the grass cover is static through time okay model done and we'll make some plots so here's the cumulative erosion or deposition over that 100 year period so I have a lot of erosion up at the ridge top which is here so the hill slope is sloping down in this direction but you notice that it's not uniform so if I'd run this model with a constant creep coefficient there would be it'd be totally symmetrical in this east west direction but because I allowed the grass to influence the erosion pattern and the grass pattern is kind of random I ended up with some accumulation of soil down here where it's blue some erosion of soil in places like here and up at the top of the ridge and some you know random looking variability so we can ask well how does this correspond to the grass cover pattern here's the grass pattern again and one of the interesting things is you you have a little bit of accumulation in places where the grass cover kind of catches the soil coming in so for example this little bar of blue here this is where soil has come to rest that corresponds with this area here where you've gone from a bare patch lots of soil coming off here being eroded to a grassy patch where it essentially gets trapped so you can see that that the grass from the agent-based modeling is influencing the what you might think of as a numerical solution a differential equation model nisdy or something like that all right well that's only one way coupling and part of the point is to explore two-way coupling here's the topography after a hundred years so here's a here's a cute little example of two-way coupling this time every time I do some soil erosion I'm going to make the rule that if the soil gets too thin the grass can't grow in a healthy way and so it gets damaged so the sheet being in the grass will influence the erosion which influences the abilities of the grass to grow which then influences the ability of the sheep to eat it's you know again this is obviously a completely toy model it's nowhere near as sophisticated as like michael's medline project examples but it you know hopefully you're getting a sense to see how simple this can be if um can be mason and landlap so I make my wool sheet model I set some parameters and this time I'm going to say I'm going to start with 20 centimeters of soil and I'm going to say you need at least 20 centimeters to have healthy grass I mean obviously I'm making this up but no just say so here I go through the same steps as before the only difference here is I'm going to add a soil layer field so now I've set everything up next block I have a little function that's going to limit grass by soil so what this will do is it will sweep through all the cells in the wool sheet grass model and for every cell where the soil has gotten too thin I'm going to kill the grass at that cell so before it was only the sheet that could kill the grass now sheep or soil getting too thin can kill it all well that's my little function and here's the main loop and I'll step through this quickly for every iteration I'm going to take the grass map have the grass influence the soil creep efficiency the creep coefficient this little line just modifies it so if the soil gets too thin the creep rate slows down so you can't have any soil creep if there's no soil to move over here I'm going to remember the previous elevation so I can calculate the net change I run my soil diffuser I update the soil thickness I limit the grass according to the soil and I run the sheep wool grass model all right so 100 years worth of interaction and before I start showing the plots you can think about is this going to look any different from the one-way coupling example do you think I mean before I just had a completely static map with no feedback what's it going to look like if there's feedback here's I mean I didn't know the answer to this before I ran it but here is so the erosion pattern again erosion in red deposition in blue so you're seeing erosion up at the ridge top and deposition down at the bottom so that basic pattern is something I would get even without the grass feedback the nature of this kind of model is that you tend to get erosion at the top because it starts out steep but there's no incoming soil to replace what goes out okay that's reasonable but this sort of patchy deposition cover down here is unusual and interesting if we look at the soil map you can see then that the the soil cover more or less mirrors the net erosion deposition but we also see that all the areas where it's really gold are the places where there's enough soil to grow veg so up here in this band up here you just you've got bare soil and it's eroded way eroding away but down here you've got sort of a nice thick cover up to 30 or more centimeters in places and if we compare that to the grass cover now the grass has basically been removed from the upper part of the slope but it's doing great down at the lower part of the slope where it's got nice healthy thick soils so whereas before you had more or less a uniform random patch now there's something systematic about it because we're honoring the soil erosion field anyway so I would I certainly don't claim there's anything profound about this but hopefully you get the sense that basic linkages like this are actually pretty easy from a computational perspective thinking about the how to frame a problem and set it up in an intelligent way that's hard but just doing the programming isn't too bad let's see I'll quickly share one other example which I was motivated to put together by partly by Moira and Dean's work and and partly from Mary and Moss's work both of you guys are thinking about groundwater so I couldn't resist doing a little groundwater example this is a laughably simple I mean the last one is laughably simple this is really simple but it simply shows that we can take a shallow groundwater model and have it interact with agents in this case the agents are highly simple but here it is I'll just go through this pretty quickly so I have to acknowledge first of all David Litwin who is a graduate student at Johns Hopkins who was the lead in writing this shallow groundwater model we published it in journal of open source software earlier this year so first a quick run of the groundwater model just to give you a sense of what I'm talking about I'll import some things and set a few parameters and I'm going to have two wells that are pumping so I'll have a recharge field here's where I'm going to create my grid I have an elevation I have the bottom of the aquifer I have the height of the water table and I have a recharge field and in this case I'm going to use the recharge field to represent some wells so most of the the little patch of land I've got here is going to be zero recharge but a few locations are going to initially two locations are going to have a pumping well so it'll be negative recharge okay that's all set up I create my component I'm going to define a couple of convenience functions so I can run my component for exactly one year there's run for one year and now I'll run it for one year with two wells in it it takes a few seconds to run we haven't really tried to speed it up so it's kind of a slow model but there it is so in this image we're looking at the elevation of the water table relative to the surface which here is all flat and you can see our water table is it basically minus two meters two meters below ground except for with these two wells where it's gone down by an extra five or six centimeters after a year's worth of pumping and you've got a nice cone of depression around each one of these okay fair enough this is shallow groundwater no big deal let's flip over this for a second but now let's introduce some agents here my agents are really really simple all they're going to do they're farmers and each farmer is going to drill a well at a random location and start pumping and they'll keep pumping until the well will runs dry and then they'll stop pumping and if the well gets watering it again they'll start pumping again so my model consists of a farmer agent which is a little agent class and all the agents do when it's their turn to act is they just check and see whether they can keep pumping or not and here's my farmer model and my farmer model is going to make a bunch of farmer agents that will populate random locations in the landscape and and that's it so that's the Asian base part here's the landline part just like we saw before a bunch of parameters set up i'm going to have they're only going to drill their wells to four meters deep and uh and they're going to pump it and outrageously high rate so that i can actually get an answer that looks sort of interesting here i create my grid i create my groundwater model to create my farmer model on a grid of the same size i have a little convenience function that creates an array that is um that is the number of wells at that cell normally just one or zero it's possible you're going to have two wells in the same cell i sort of think about like the fence line runs through the cell and each farmer decided to drill their well right next to the darn fence um so that's all that does so okay so because i haven't ceded the random number generator every time i run this it looks different so we'll see if this is interesting or not so here we have a a four by four kilometer patch of flat land with i think it's i mean is that like 10 farmers or 12 farmers who have drilled wells in these locations so i'll set the recharge to be zero everywhere except where there's a well so that's the recharge rate it's just a mirror image of that and now we're going to run for several years and each year i'm going to update the groundwater model i'm going to update the depth to water table i'm going to run the farmer model which again just means they're going to check and see if they can keep pumping or not i'm going to get some information about how many wells are still able to pump i will update the recharge according to who's pumping and who's not and we'll plot a little figure this is going to take a few minutes so i'll back up and go through that same sequence of events a little more slowly while that's cooking so this first function runs the groundwater model for one year the next one just says the depth of the water table is the elevation of the land minus the height of the water table where we run the farmers here we find out an array that says not just how many wells do you have at each grid cell but how many pumping wells do you have again normally one is zero and we'll have a little report here we'll calculate take the recharge field and this what this line does is it says take the number of pumping wells in that cell multiply them by the pumping rate for one well and that's your recharge field so for most of those it'll be zero because there's zero pumping wells uh great can i ask you a question of course are there any issues here with a temporal resolution of some of these steps like for example like when when we do uh the hydrological models in that logo or or in the agent based modeling uh framework um you know we can't just lump it all in like what happens like hydrologically in one year we actually have to to divide it into sub steps for the continuity of the hydrological surface so is that something that you also have to deal with just be careful about like as you're as you're coupling different you know processes that have different temporal resolution you know that's a great question we're absolutely i mean this so this little uh hidden under the hood of this run for one year function that i wrote um actually what's happening is it's running for a whole bunch of much smaller time steps where's my run for one year function because the the groundwater model goes unstable if you take a time step right exactly exactly so but that's an important aspect of coupling right when we're thinking of so so that's something to kind of like maybe just just consider and pay pay attention to um when we're thinking of using these different tools together yeah totally totally and you you know i'm i'm in so i'm i have to use a time step that works for my numerical solution model right as i get nonsense right but at the same time for efficiency it maybe isn't necessary to you know update the agent side every little micro iteration exactly we ended up i had to play around with this a month but i got it to the point where i can run 3600 seconds as time steps but it depends highly because it's a non-linear problem it depends highly on the you know thickness of the aquifer and the conductivity and whatnot so exactly right and that that's sort of what i tried to bury in this just run for one year which says take whatever time step size you've got and do however many time steps you need to get through one year and then we'll go back right so okay so i this is you know this is very rough so i had a whole bunch of printouts to record who's pumping when in what year but down here below this somewhere there's a okay well it looks like the farmers wells have started to run dry playing with this i find sometimes they all run dry at once and sometimes one will run dry another one did you see like any ringing like you know kind of like up and down and up and down in my very short exploration of this a little bit sometimes yeah we're like a little person that i ran it it went down to zero and then it came back up again briefly and then it went back down to zero again yeah because if you stop pumping the cone of depression collapses back into your well and or if your neighbors stop pumping because they drilled a little bit too much then maybe it takes a little heat off your well like if you had different depths of wells that starts to get interesting right so that that's also where the temporal resolution because we have that too and and so like of course when we're working with stakeholders like but the wealth don't behave like that i'm like well yeah i know because we're kind of like lumping all the decisions like as an annual decision decisions like the pumping and the pumping also isn't annual right so it will respond to the levels of water so like just like just to say that there are these aspects to consider the just the temporal resolution of of of both the hydrological and the decision making side yeah yeah i totally agree i mean i really this is just intended to be technical demonstration of how to work it technically but there's all kinds of conceptual issues like that i mean in this case it looks like uh you know you can see the cones of depression around all these wells and because there's a bunch clustered here and right next to the boundary they've drawn it down drawn down the aquifer more over here than over here so this well looks like it might last longer than some of the others right and let's see so there they go they're still all happy and then yeah here's this one year when they all had to stop pumping the aquifer started to smooth itself out again right now that's allowed some of the wells to be viable again so they started to pump again now they've died out and and that's that's it because i'm not adding it all the during the water so each point where it's just gone but anyway hopefully this conveys a little bit of the sense of that it's from a technical standpoint in terms of writing the code it's not necessarily that complicated right i think it's more complicated to think about time stepping and what's the right time scale and how to get it realistic and what are the realistic inputs and all that but i was i was pleasantly surprised by how easy it was to construct this toy example with mesa because it's because it's a nice little tool anyway i'll stop there but that um these notebooks are both on that website for anyone that's cool thanks for sharing one quick question greg at one point did you try this with net logo at all or did you make a choice over of one versus the other or i don't know i'll work to be to be perfectly honest i was going to do this with pine net logo and i ran into technical issues and i didn't have a lot of time this is like several days ago and i thought well let me just check out mesa because it seemed like katie was able to get mason to work really fast and i went on mason i did their initial tutorial and because it's written in in a an object-oriented way that it feels familiar right i just went right right knowing also that matt has been working with pine net logo and so he could show that side yeah just just was curious about like you know it's good to know like that the experience is different and like one made it different between one and the other but yeah