watershed-1.1.2
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
VERSION
$Id: watershed-1.1.2.nlogo 37529 2008-01-03 20:38:02Z craig $
WHAT IS IT?
A terrain generator demo and watershed simulator, with a nifty 3-d terrain visualizer thrown in as a bonus.
HOW IT WORKS
The patch "elev" is the hard surface of the terrain. Level is the measure of the current surface level. If the patch is dry, level is the same as elev. If the patch is wet, then level is greater than elev by the depth of the water.
To simulate the flow of water, each "wet" patch compares it's own "level" with the level of it's neighbors. If any neighbor has a lower level, the patch finds one of the neighbors with the very lowest level, figures the difference between the two levels, and shares half of that difference with the low neighbor. In other words, water pours from the patch to it's lowest neighbor to make both patches level. All the water on the high patch could pour into the low patch, if needed.
HOW TO USE IT
GENERATE TERRAIN:
To get started, click one of the terrain generator buttons. The model comes with river valley and volcano (atoll) generators.
ADD WATER
To add water to the river, click the river? switch on.
Water flows from the head of the river.
The head is defined as the point of lowest elevation on the top row. That may not be at the center of the row.
Click on Drain? to contantly remove water from the bottom row.
To make the volcano "erupt" click the erupt? switch on.
Water flows from the center of the volcano. I know, it's silly.
To add water to the entire surface of the terrain (to turn the volcano into an atoll, for example) click the rain, rain-hard, or quick-fill buttons. Rain-hard is 100 X the normal rain-rate. Rain and rain-hard add to the already present water, if any. Quick-fill sets the water depth to be even with the mean elevation of the entire terrain.
To create a flash-flood, click the flood button. The top row gets flooded.
The dry-all button removes all the water from the terrain.
MAKE IT FLOW:
Click the Flow button. The water on the terrain will seek it's own level. Rivers flow, lakes form, dams fill, lava flows, islands emerge from the sea!
3-D Visualization
~~~~~~~~~~~~~~~~~
To see the terrain in 3-D, click the "setup-3d" button.
After that, if you make changes in the terrain, or to see the effects of water flow, click the "render-3d" button to update the display.
To clear the 3-d display, click the clear-3d button.
The animate button continuously refreshes the 3-d display, useful when adjusting the tilt and spin sliders.
The auto-spin switch causes the animate button to continuously changes the spin slider, as well.
OTHER CONTROLS:
~~~~~~~~~~~~~~
The label? siwtch turns on the labeling of the patches with their current water depth.
If altitude? is on, the label shows the actual level, rather than the water depth.
The false-color? switch causes the model to use a different coloring scheme, that exposes the elevations differently.
The altitude? switch alters the way the water is colored.
Altitude? on colors by the surface level of the water.
Altitude? off colors by water depth.
THINGS TO NOTICE
Notice how water flows downhill! I'm a fricken genius!
THINGS TO TRY
What conditions will cause the river to overflow it's banks? How do you think this compares to real-world flood conditions?
Import some real terrain data, perhaps from a geographic information system.
Does the model-generated flow match the real-world flows on that terrain?
EXTENDING THE MODEL
Add additional terrain generators: cistern, septic field, mountain.
Generate a terrain that has one straight river and one curvy river. Is the flow rate different?
~~~~~~~~~~
Add the effect of erosion from the passage of water.
Allow for different types of ground (soil, sand, rock, clay) that erodes differently.
Further, allow for each elevation to be a different type of rock so as erosion occors, different layers are exposed, affecting the rate of erosion.
Further, make it so each patch has strata.
~~~~~~~~~~
Add the ability to track, measure, whatever the direction and velocity of the water flow. Perhaps a turtle on each patch can show the direction that the water flowed, and remember how much water it was. Or perhaps the sliding mean of the directions and amounts.
Then put boats or flotsom in the water, moving with the currents!
~~~~~~~~~~
The model treats the ground as completely waterproof. However, in the real world, different ground types absorb water differently. Rock, none. Sand, lots! Sandlots! Get it? Anyway, water flows *below* the surface, *through* layers. Expand the model to allow water to flow through permeable surface layers.
Ok, now this is crazy: extend the model to support multiple strata with different permiabilities, including voids, and all water to flow through, around, and between the layers. This would allow for undergound springs, water-tables, and predicting otherwise unexpected run-off behaviors due to water-permeable subsurface layers.
~~~~~~~~~~
Enhance the 3-D visualizer. It is fairly primitive, and could use the following enhancements:
Z-order clipping: Hide nodes that should be behind other nodes.
Perspective: The current view is an orthagonal projection. Add a perspective projection.
Additional rotations: How about x-axis rotation?
3D detail adjustment: For models with low resolution, the option to add additional nodes between the "real" nodes, so that the 3-d view is smoother. For models with high resolution, the option to reduce the number of 3d nodes to improve performance of the 3-d view
NETLOGO FEATURES
Patch Scheduling:
Because the patches execute code in a particular order, a bias is introduced that tended to make water flow much faster in some directions that in others. To reduce the effect of this bias, which is due to water flowing to adjacent patches in the same order they are executed, the model updates patches randomly. Each time through the "flow" loop, only 1 in 5 patches are updated.
CREDITS AND REFERENCES
Thanks to Boyce J Baker, who by seeking assistance on a model of his own, got me thinking about the fun of modeling a watershed.
COPYRIGHT &
LICENSE
This work is Copyright ? 2004 James P. Steiner.
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/1.0/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
Comments and Questions
; Watershed Model and Terrain Generator ; Version 1.1.2 ; James Steiner globals [ ; levels-changed ; obsolete, used to flag if levels changed, to notify 3d update peak ; the highest level of all the patches middle ; the mean of the elev and level valley ; the lowest elev of all the patches spread ; the difference between the valley and peak vm ; the valley-middle line, used for coloring pm ; the peak-middle line, used for coloring depth ; the lowest elev or the greatest depth of the wet patches surface ; the elevation of the highest water ; both of the above normally equal to spread and peak _ticks ; count of flow-frames rendered, for by-eye estimation of fram rate ] breed [ backdrops ] breed [ nodes ] nodes-own [ my-patch ; the source patch linked to this node ox oy oe ; original coordinates px py pel ; projected coordinates pre-hide? ; part of the projection process ] patches-own [ elev ; "surface" level level ; "water" level, equals elev when dry ; may never be less than elev volume ; level - elev, the depth of the water, or the volume of water temp ; used for various things temp2 temp3 neighbors-nowrap ; the neighbors, without edge-wrapping ] to startup ; river-valley end to update-all ; apply color and, if required, labels no-display ; freeze display while updating color-all ; apply color label-all ; apply labels display ; refresh display ; set levels-changed 1 end to dry-all ; resets the "water" level to the elevation ; effectively drying the landscape ask patches [ set level elev ] calc-measures update-all end to diffuse-elev-nowrap ask patches [ set level .5 * ( elev + mean [ elev ] of neighbors-nowrap ) ] ask patches [ set elev level ] end to define-neighbors-nowrap ask patches [ set neighbors-nowrap neighbors in-radius-nowrap 2 ] end to river-valley let lump-size 0 let num-lumps 0 ; generates a passable simulation of the elevations of a river valley ; flowing north to south clear-turtles clear-patches define-neighbors-nowrap note "creating valley contours" ; impress a valley shape ; store in LEVEL ask patches [ do-valley ] set valley min [ level ] of patches set peak max [ level ] of patches if valley = peak [ set valley valley - 2 set peak peak + 2 ] set spread peak - valley ;adjust valley to 0 .. 1 ask patches [ set elev ( level - valley ) / spread * max-pxcor] note "adding random lumps" dry-all wait .5 set num-lumps sqrt (world-width * world-height) * ( 1 - lumpiness * .01 ) ask n-of num-lumps patches [ set lump-size 1 + max-pxcor * .01 * (random-float lumpiness) without-interruption [ ask patches in-radius-nowrap lump-size [ set elev elev + lump-size - ( distance-nowrap myself ) ] ] ] note "tilting landscape" dry-all wait .5 ; tilt the landscape so everything runs downhill ; slope set by steepness ask patches [ set elev elev + (pycor / max-pycor ) * spread * steepness * .02 ] note "" dry-all end to normalize-elev ; set min to 0, max to 100 calc-measures ask patches [ ; set min to 0 set elev (elev - valley ) ; set max to max-pxcor set elev elev * 100 / spread ] ; adjust valley, peak, spread, middle set valley 0 set peak max-pxcor set spread max-pxcor end to do-valley let elev-east-west 0 let elev-north-south 0 let elev-meander 0 let px% 0 let py% 0 let adj-px% 0 let px-cos 0 let sweep-width 0 let meander-freq 0 let pwr 0 set pwr 1 set px% pxcor / max-pxcor ; pxcor ==> -1 .. 1 set py% 1 - ( pycor + max-pycor ) / world-height ; pycor ==> 0 .. 1 set sweep-width .01 * meander% ; .25 + .25 * sin ( py% * 45 ) set meander-freq py% * 180 * 4 set adj-px% ( (px% + sweep-width * sin ( meander-freq ) ) ) set elev-meander (abs adj-px%) set level elev-meander ; set elev elev * ( 1 - scale) + level * elev-meander * scale end to calc-measures ; caluclate peak, valley, spread set peak max [ elev ] of patches set valley min [ elev ] of patches if peak = valley [ set peak peak + 2 set valley valley - 2 ] set middle (peak + valley) * .5 set spread abs ( peak - valley ) set vm (valley + middle) * 0.5 set pm (peak + middle) * 0.5 ifelse altitude? [ set depth peak ] [ set depth spread ] end to add-wall ; add wall along back / top to prevent water ; from flowing backwards wrapping from bottom, etc. ; first, caluclate peak, valley, spread set peak max [ elev ] of patches set valley min [ elev ] of patches set spread abs ( peak - valley ) ; use values to elevate back edge %10 of depth of model ask patches with [ pycor = max-pycor ] [ set elev peak + spread * .1 ] ; scale it up ; ask patches ; [ set elev elev * 1000 ] dry-all end to add-dam let height 0 let spillway 0 ; adds a dam-like structure to the map set height 1.3 * mean [ elev ] of patches set spillway [elev] of patch 0 0 + ( height - [elev] of patch 0 0 ) * .5 ask patches with [ pycor = 0 and abs pxcor < max-pxcor / 2.0 and elev < height ] [ set elev height ] ask patch 0 0 [ set elev spillway ] dry-all end to volcano let deepest 0 let peaks 0 ; build an irregular, circular island ; with a shallow center lagoon ; "clear patches" cp ; "clear turtles" ct ; "define neighbors no-wrap" define-neighbors-nowrap ; turn off river mode set river? false ; "create overall ring shape" ask patches [ ; get distance from center ; "doing math" set temp distancexy 0 0 ; sin wave, 0 at center, peak in middle, 0 at corners set temp3 temp * 360 / 3 / max-pxcor ; scale as distance from edge set temp2 2 * sin ( temp * 180 / max-pxcor ) * ( max-pxcor - abs pxcor) / max-pxcor * ( max-pycor - abs pycor) / max-pycor set elev world-width * sin temp3 * temp2 ] ; "add random peaks and dips, erode, repeat" repeat max-pxcor [ ; "picking peak/pit location" set [elev] of patch 0 0 (- world-width) set peaks n-of max-pxcor patches ; "talking to peaks" ask peaks [ ; "set temp" set temp random 2 * 2 - 1 ] ; "talking to peaks" ask peaks [ ; "set elev" without-interruption [ set elev elev + max-pxcor * temp ] ] ] repeat 4 [ set [elev] of patch 0 0 (min-pxcor) diffuse-elev-nowrap ] ; add "stress ridges" ask patches [ ; get distance from center set temp distancexy 0 0 ; get angle from center ifelse temp = 0 [ set temp2 0 ] [ set temp2 ( towardsxy 0 0 + 180 ) if temp2 > 360 [ set temp2 temp2 - 360 ] ] ; pick number of ridges set temp3 temp2 * max-pxcor / 3 set elev elev + max-pxcor * sin temp3 * sin temp * .2 ] dry-all end to rain ; add water to entire surface, using rain-rate slider ; adds depth of rain that is up to 1/10000 the height of the terrain ask patches [ set level level + rain-rate * spread * .0001 ] update-all end ; rain to rain-hard ; adds depth of rain that is up to 1/1000 height of terrain ask patches [ set level level + rain-rate * spread * .001 ] update-all end ; rain-hard to do-sources-and-drains ; adds water at top center of window if river? [ ask min-one-of patches with [ pycor = ( max-pycor - 1 ) ] [ elev ] [ set level level + source-rate ] ] if erupt? [ ask patch 0 0 [ set level level + source-rate ] ] if drain? [ ; removes water from bottom ask patches with [ pycor = (- max-pycor) ] [ set level level - volume * .1 ] ] end ; do-sources-and-drains to evaporate-all ; reduce water level by "evap rate" ; which is linear and not proportional ; as it is due to surface area, not volume if e-rate > 0 and evap? [ ask patches with [ level > elev ] [ set level level - e-rate if level < elev [ ; don't allow level to be below elev! set level elev ] ] ] end ; evaporate-all to flow-all evaporate-all ; to reduce flow bias created by natural netlogo patch code scheduling, ; only update 1 in 5 patches every turn ask patches with [ level > elev and random 5 = 0 ] [ flow-ver-1 ] ; add water every 5 turns if ticks mod 5 = 0 [ do-sources-and-drains update-all ] set _ticks _ticks + 1 if _ticks > 1000000 [ set _ticks 0 ] end to flow-ver-1 ; if any neighbors with lower level ; pick random one of neigbors with LOWEST level ; move 1/2 of difference in level to that neighbor ; (so both are at a level) let local-min 0 let min-level 0 let extra 0 let portion 0 let max-portion 0 without-interruption [ if level - elev > 0 ; if I am wet... [ set min-level min [ level ] of (neighbors-nowrap) if level > min-level [ set local-min one-of (neighbors-nowrap) with [ level = min-level ] set extra level - min-level ifelse extra < .001 ; if less than 1/1000 unit, it all flows down [ set portion extra ] [ set portion extra * .5 ; if portion is more than is here, just take all of it if portion > ( level - elev ) [ set portion level - elev ] ] ; adjust the levels set level level - portion ask local-min [ set level level + portion ] ] ] ] end to label-all ; are labels requested? ifelse labels? [ ; yes. labels are requested ; ; altitude, or water depth? ifelse altitude? [ ; ; altitude / surface level ask patches [ set plabel (int (level)) ] ] [ ; show depth ask patches [ set plabel (int (level - elev)) ] ] ] [ ; no labels ; does patch 1 1 have a label? if [plabel] of patch 1 1 != "" [ ; it does, implying that all patches have labels. ; so, clear all labels ask patches [ set plabel "" ] ] ; this would seem to be faster than clearing all the labels every cycle ] end to color-all ; prestore the value of "volume" every 0 [ ; find peaks, valleys, etc. used later for colorer, scaling. ; calc-measures ] ifelse hide-water? [ ; use elev, not level, for display, and don't show water colors ifelse false-color? [ ; color using rainbow, to show-off contours ask patches [ set pcolor 20 + 7 * scale-color gray elev valley peak ] ] [ ask patches [ set pcolor get-earth-color ] ] ] [ ; use level for display, using water colors as needed. ask patches [ set volume level - elev ] ifelse false-color? [ ; color using rainbow, to show off contours ask patches [ set pcolor 20 + 7 * scale-color gray level valley peak ] ] [ ask patches [ set pcolor get-color ] ] ] end to-report get-color-from [ agent ] let result 0 ask agent [ set result get-color ] report result end to-report get-color ; patch procedure ifelse volume <= 0 [ report get-earth-color ] [ report get-water-color ] end to-report get-water-color ; patch procedure ifelse altitude? [ report blue - 4 + .8 * scale-color gray level valley surface ] [ ifelse volume < .010 or erupt? [ report red + 4 - .8 * scale-color gray volume 0 depth ] [ report blue + 4 - .8 * scale-color gray volume 0 depth ] ] end to-report get-earth-color ; patch procedure ifelse elev <= vm [ report gray - 4 + .8 * scale-color gray elev valley middle ] [ ifelse elev <= pm [ report green - 4 + .8 * scale-color gray elev valley peak ] [ report brown - 4 + .8 * scale-color gray elev middle peak ] ] end to setup-3d clear-turtles ; create a turtle to use as a backdrop to hide the patches ; (instead of coloring the patches black) create-backdrops 1 [ setxy 0 0 set color black + 1 set shape "box-large" set size world-width ] ; these turtles, one for each patch ; show the points of elevation ask patches [ ; make a node turtle sprout 1 [ set breed nodes set my-patch patch-here set color pcolor set shape "circle-large" set size 1.0 set heading 0 set ox xcor set oy ycor set oe level ] ] render-3d end to render-3d let insetx 0 let insety 0 let insetw 0 let inseth 0 let insett 0 let insetl 0 let insetb 0 let insetr 0 if not any? backdrops [ stop ] set insetx max-pxcor * shift-x set insety max-pycor * shift-y set insetw max-pxcor * scale set inseth max-pycor * scale no-display ask backdrops [ setxy insetx insety set size insetw * 2.1 ] ask nodes [ set oe [level] of my-patch set color [pcolor] of my-patch ; scale elevation so max-pxcor cubic volume fits into 1/2 screen-height set pel ( oe - valley ) / world-width * max-pycor + min-pycor * .5 ; spin X set px ox * cos spin + oy * sin spin ; spin and tilt Y set py (oy * cos spin - ox * sin spin) * cos tilt + pel * sin tilt ; scale and adjust center set px px * scale set py py * scale set pre-hide? ( abs px > insetw or abs py > inseth) set px px + insetx set py py + insety set hidden? pre-hide? or ( abs px > max-pxcor or abs py > max-pycor ) setxy px py ] display end to clear-3d ask backdrops [ die ] ask nodes [ die ] update-all end to note [ text ] ask patch 0 0 [ ifelse text = "" [ set plabel "" ] [ set plabel text ] ] end
There is only one version of this model, created over 14 years ago by Uri Wilensky.
Attached files
No files
This model does not have any ancestors.
This model does not have any descendants.