;==================== begin diffuse-in-bounds.nls ==============================
; diffuse-in-bounds - diffuse patch variable with boundary constraints.
;
; By Rik Blok, 2013 <http://www.zoology.ubc.ca/~rikblok/wiki/doku.php>
;
; This is free and unencumbered software released into the public domain.
;
; Anyone is free to copy, modify, publish, use, compile, sell, or
; distribute this software, either in source code form or as a compiled
; binary, for any purpose, commercial or non-commercial, and by any
; means.
;
; Provides:
;  
;   diffuse-in-bounds
;     Same as diffuse but only over patches in bounds.
;   diffuse4-in-bounds
;     Same as diffuse4 but only over patches in bounds.
;
; Usage:
;
;   diffuse-in-bounds  "_patch-variable_"  _fraction_  task [ _is-in-bounds?_ ]
;   diffuse4-in-bounds "_patch-variable_"  _fraction_  task [ _is-in-bounds?_ ]
;
; Example:
;
;   patches-own [ aroma ]
;   to go
;     ; diffuse aroma thru green patches
;     diffuse-in-bounds "aroma" 0.5 task [ pcolor = green ]
;   end
;
; Known limitations:
;
;   2013-08-18 - patch-variable must be passed as a string.  Is there a better way?
; 
; Revisions:
;
;   2013-08-18 - initial release by Rik Blok
;-------------------------------------------------------------------------------

patches-own
[ diffuse-in-bounds-temp
]

to diffuse-in-bounds 
; Same as diffuse but only over patches in bounds.
; Parameters:
[ dib-patch-variable ; Patch variable to diffuse, as a string.
  dib-fraction       ; Fraction of variable to share.
  dib-is-in-bounds?  ; Is patch in bounds?  True/false reporter task.
]
  ; pass one eighth to each neighbor.  If less than 8 neighbors, hold on to excess
  set dib-fraction dib-fraction / 8 ; how much to pass from each neighbour
  ask patches with [ runresult dib-is-in-bounds? ]
  [ let neighbors-in-bounds neighbors with [ runresult dib-is-in-bounds? ]
    ; change = incoming - outgoing
    set diffuse-in-bounds-temp dib-fraction
                               * ( sum [ runresult dib-patch-variable ] of neighbors-in-bounds
                                   - count neighbors-in-bounds * runresult dib-patch-variable
                                 )
  ]
  ask patches with [ runresult dib-is-in-bounds? ]
  [ run (word "set " dib-patch-variable " " dib-patch-variable " + diffuse-in-bounds-temp" )
  ]
end

  
to diffuse4-in-bounds 
; Same as diffuse-in-bounds but only over 4 nearest neighbors.
; Parameters:
[ dib-patch-variable ; Patch variable to diffuse, as a string.
  dib-fraction       ; Fraction of variable to share.
  dib-is-in-bounds?  ; Is patch in bounds?  True/false reporter task.
]
  ; pass one quarter to each neighbor.  If less than 4 neighbors, hold on to excess
  set dib-fraction dib-fraction / 4 ; how much to pass from each neighbour
  ask patches with [ runresult dib-is-in-bounds? ]
  [ let neighbors-in-bounds neighbors4 with [ runresult dib-is-in-bounds? ]
    ; change = incoming - outgoing
    set diffuse-in-bounds-temp dib-fraction
                               * ( sum [ runresult dib-patch-variable ] of neighbors-in-bounds
                                   - count neighbors-in-bounds * runresult dib-patch-variable
                                 )
  ]
  ask patches with [ runresult dib-is-in-bounds? ]
  [ run (word "set " dib-patch-variable " " dib-patch-variable " + diffuse-in-bounds-temp" )
  ]
end

  
;==================== end diffuse-in-bounds.nls ================================
