watershed-1.1.2

No preview image

1 collaborator

Uri_dolphin3 Uri Wilensky (Author)

Tags

(This model has yet to be categorized with any tags)
Model group CCL | Visible to everyone | Changeable by group members (CCL)
Model was written in NetLogo 4.0pre8 • Viewed 1036 times • Downloaded 46 times • Run 5 times
Download the 'watershed-1.1.2' modelDownload this modelEmbed this model

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

Please start the discussion about this model! (You'll first need to log in.)

Click to Run Model

; 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.