25  Calculating water flow accumulation

25.1 Water flow algorithm

To calculate land productivity, we use our GIS data combined with parts of the Land submodel in the Indus Village model (Angourakis 2021). In this step, we aim to assign a flow accumulation value to each patch based on its relative elevation within the terrain. This serves as a proxy for the region’s hydrology beyond the river data we have.

The submodel is based on the algorithm described in Jenson & Domingue (1988), as implemented by Huang & Lee (2015).

Jenson, S. K., and J. O. Domingue. 1988. ‘Extracting Topographic Structure from Digital Elevation Data for Geographic Information System Analysis’. Photogrammetric Engineering and Remote Sensing 54 (11): 1593–1600.

Huang, Pin Chun, and Kwan Tun Lee. 2015. ‘A Simple Depression-Filling Method for Raster and Irregular Elevation Datasets’. Journal of Earth System Science 124 (8): 1653–65. https://doi.org/10.1007/s12040-015-0641-2.

25.2 Adding the main procedures

The algorithm uses a numeric codification of the eight neighbour directions and a tag that classifies patches as “start”, “pending”, “done”, progressively converting the former into the latter. Patches on the edge of the map are automatically directed toward the outside. Because this is a significant piece of code based on a specific reference, we will enclose all related procedures within a special commentary note:

Outside this enclosed section, we add the two main procedures set-flow-directions and set-flow-accumulations inside a higher-level setup-flows:

We add a final step to get maxFlowAccumulation, which we need for scaling.

25.3 Visualising flow accumulation

As usual, we need to add some extra code to visualise the outcome. In this case, however, we want to observe flow direction, flow accumulation, and elevation simultaneously. For this, we will use an accessory agent type whose only function is representing the flow of patches on top of its colour.

Flow accumulation is visualised as links between flowHolder agents created on patches. The links’ thickness and colour represent the flow accumulation values.

Now, press “setup”. Calculating the variables is relatively fast, but displaying all flowHolders takes some time.

View of flow direction and accumulation, calculated with ‘flows’ module
View of flow direction and accumulation, calculated with ‘flows’ module

25.4 Assessing fit

To better visualise how much flow_accumulation actually accumulates, let us run the following “highlight” command directly in the console:

Highlight of patches with flow accumulation greater than 10
Highlight of patches with flow accumulation greater than 10

Focus view on a sample of patches:

patch view
patch 70 145
patch 179 69
patch 70 145
patch 201 108
patch 125 99
patch 54 76

Our approximation of the region’s hydrological system is definitely not perfect. At a minimum, we want the main river, Lithaíos, to emerge, even if following an approximated path. The problem likely comes from our previous step: reducing the resolution of the original DEM. The height map we are using has many “sinks” (i.e., patches not at the edge with the lowest elevation among their neighbours).

Worse, it might be that the roughness of the terrain escapes even the lowest of the resolutions treatable at this scale, to a point where the pathways of rivers cannot be retraced using height maps. Let us work with the first hypothesis and address the sinks in our processed height map.

25.5 Improving fit with fill-sink

We can improve our results by using the fill-sink procedure in the original Land model implementation (see code in the Indus Village repository), based on Huang & Lee (2015).

This procedure fills up the elevation of “sink” patches so flow can continue moving until it reaches the edge of the map.

First, we can identify sink patches with the following procedure:

We then used it together with our previous “highlight” command in the console:

Highlight of sink patches
Highlight of sink patches

We then implement the fill-sinks algorithm:

After running setup again, we obtain a much better result. We can now clearly identify what should be the Lithaíos River, and its path is close to our original river data.

View of flow direction and accumulation, calculated with ‘flows’ module with the fill-sinks procedure
View of flow direction and accumulation, calculated with ‘flows’ module with the fill-sinks procedure

Highlight of patches with flow accumulation greater than 10
Highlight of patches with flow accumulation greater than 10, after we include the fill-sinks procedure

We should remember that this algorithm modifies our original DEM heightmap and costs more computational resources/time.

25.6 Implementing a feature to export and import world

We do not want to repeat this every time we initialise a simulation run. Therefore, we will export the entire map configuration to a file for later use. We do this quickly with “File > Export… > Export World” and selecting the data folder. We could write procedures to export (and import) a subset of data. Still, this option is much faster, since this is the initial spatial data we want for all future versions.

Still, if you need to do this several times and want to keep track of the directory and file you are using, you can add a button to the interface with the following code, which is equivalent to the built-in option in the menu:

You can do the same to import the file. Inside a new button, add:

Now you can export and import your map with flows.

See the fully implemented version of this module: BlockC_module2_flows.nlogo.

For the sake of this example, we will assume our approximation is sufficient. Still, tackling this kind of problem and exploring other solutions in your own time could be an excellent exercise for improving your skills.