02 OamLab V1.10

02 OamLab V1.10 preview image

1 collaborator

121210_portrait_of_garvin Garvin Boyle (Author)

Tags

atwood's machine 

Tagged by Garvin Boyle over 7 years ago

biophysical economics 

Tagged by Garvin Boyle over 7 years ago

ecological economics 

Tagged by Garvin Boyle over 7 years ago

maximum power principle 

Tagged by Garvin Boyle over 7 years ago

sustainability 

Tagged by Garvin Boyle over 7 years ago

sustainable economics 

Tagged by Garvin Boyle over 7 years ago

Model group Sustainability | Visible to everyone | Changeable by group members (Sustainability)
Model was written in NetLogo 5.0.5 • Viewed 914 times • Downloaded 39 times • Run 0 times
Download the '02 OamLab V1.10' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


Info tab cannot be displayed because of an encoding error

Comments and Questions

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

Click to Run Model

;;-----------------------------------------------------------------------------|
;; SECTION A – AUTHOR IDENTIFICATION AND CODE ABSTRACT
;;-----------------------------------------------------------------------------|
;;
;; File Name: OamLab_V1.10.nlogo
;; By Orrery Software
;; Dated: 2015-01-28
;; Author contact:
;;   Garvin H Boyle
;;   orrery@rogers.com
;;   orrery-software.webs.com

;; As the author, I welcome questions, discussion of issues and suggestions
;;   for improvements.

;;-----------------------------------------------------------------------------|
;; This OamLab app is a laboratory in which students can study the MPP.

;;-----------------------------------------------------------------------------|
;; SECTION B – INITIAL DECLARATIONS OF GLOBALS AND BREEDS
;;-----------------------------------------------------------------------------|
;;
;;-----------------------------------------------------------------------------|
;; This program was developed on NetLogo Version 5.0.5
;;

;;-----------------------------------------------------------------------------|
;; code-determined global variables
globals
[
  ;; The version should be coded in this global variable to be included in
  ;;   output files.
  gs-Version
  
  ;; Note: Some global variables are declared inside of switches, sliders and 
  ;;   choosers when the interface is constructed and are not declared here.
  ;;   For the sake of clarity and completeness, they are noted here.
  
  ;; There are several uses of global variables:
  ;;  - Toggles (switches), and choosers which enable or disable features;
  ;;  - Numbers (in variables or sliders) which act as parameters;
  ;;  - Numbers (in variables) which collect data.
  ;;
  ;; Those marked as 'native Boolean' have values of true or false.
  ;; Those marked as 'numeric Boolean' have values of 1 or 0.
   
  ;;---------------------
  ;; MODELING ENVIRONMENT
  ;;---------------------
  
  ;; Assumed “Model Settings” on startup
  ;; horizontal wrap: off
  ;; vertical wrap: off
  ;; location of origin: bottom left
  ;; patch size: 9.63 pixels
  ;;-----------------------------------------------------------------------------|
  ;; Implicit global variables due to model settings – patch locations
  ;; min-pxcor  0
  ;; max-pxcor  15
  ;; min-pycor  0
  ;; max-pycor  31
  
  ;;----------------------------
  ;; SCENARIO SELECTION CONTROLS
  ;;----------------------------
  
  ;; gs-scenario       ;; Chooser, string converts to a scenario number
  g-scenario-number    ;; scenario number, 0, 1 or 2; interpretation of gs-scenario

  ;; The possible scenarios.
  g-scenario-low-e     ;; scenario 0
  g-scenario-high-e    ;; scenario 1
  g-scenario-mixed-e   ;; scenario 2

  ;; gs-fitness-measure  ;; Chooser, string converts to a fitness number
  g-fitness-number     ;; scenario number, 0, 1 or 2; interpretation of gs-scenario

  ;; The possible scenarios.
  g-fitness-joint      ;; Fitness-number 0
  g-fitness-time       ;; Fitness-number 1
  g-fitness-energy     ;; Fitness-number 2
  
  ;; The special scenario.
  ;; g-set-max-head-size  ;; Has it's own input box
  
  ;; To halt a scenario at a pre-determined tick.
  ;; g-halt-at-tick       ;; Has it's own input box

  ;; Initialize the Pseudo Random Number Generator (PRNG).
  ;; g-use-this-seed      ;; Slider, ( 1 <= g-use-this-seed <= 100 )

  ;;-----------------------------------------------
  ;; BIOPHYSICAL SUB-SYSTEM CONTROLS AND PARAMETERS
  ;;-----------------------------------------------

  ;; Structural control parameters (Sliders)
  ;; g-no-of-chains-at-start     ;; The initial number of primed chains
  g-no-of-chains-max             ;; The maximum number of primed chains
  ;; g-length-of-chains          ;; The fixed length of all chains
  ;; g-drop-distance             ;; The distance a mass falls (D)
  ;; g-acceleration              ;; Acceleration due to gravity (g).
  
  ;; Chain structures
  g-no-of-chains                 ;; The current number of primed chains
  g-next-chain-sn                ;; The serial number of the next chain born
  gl-new-chain                   ;; a list in which a new chain is constructed
  gl-chains-lib                  ;; a list containing all chains
  gl-chains-indices              ;; a list if indices into gl-chains

  ;;-------------------------------------
  ;; SPECIAL SCENARIO
  ;;-------------------------------------
  g-max-head-size
  g-min-tail-size
  
  ;;-------------------------------------
  ;; END OF MODEL PARAMETERS AND CONTROLS
  ;;-------------------------------------
  
  ;;-------------------------------------
  ;; DATA COLLECTION AND DISPLAY CONTROLS
  ;;-------------------------------------
  
  ;; The following global variables are not model controls or paramaters, 
  ;;   but, rather, are variables used to collect data about the model 
  ;;   for display in the user interface, in some fashion (monitors or plots),
  ;;   or used to manage all of the debug routines and output.
  
  ;; SYSTEM-WIDE AGGREGATES
  ;; Used to verify conservation of cash, mass and energy.
  ;; Also used to make 'balance sheet' display on interface.

  ;; also g-no-of-chains above.
  g-no-of-hoams             ;; count of all HOAMs
  g-no-of-heads             ;; count of all heads
  g-no-of-bodies            ;; count of all bodies
  g-no-of-tails             ;; count of all tails

  ;; These lists have g-length-of-chains entries. 
  gl-ttl-lg-nrg-per-hoam    ;; list; total of unusable energy
  gl-ttl-mass-per-hoam      ;; list; total mass
  ;; These lists have ( g-length-of-chains - 1 ) entries.
  gl-ttl-hg-nrg-per-oam     ;; list; total of usable energy
  gl-pi-Mj-per-oam          ;; list; product of joint fitness measures
  gl-pi-Mt-per-oam          ;; list; product of time fitness measures
  gl-pi-Eu-per-oam          ;; list; product of Odum Efficiency measures
  gl-geo-Mj-per-oam         ;; list; GeoAve of joint fitness measures
  gl-geo-Mt-per-oam         ;; list; GeoAve of time fitness measures
  gl-geo-Eu-per-oam         ;; list; GeoAve of Odum Efficiency measures

  gl-ttl-hg-nrg-per-tick    ;; list; average of usable energy
  gl-ttl-lg-nrg-per-tick    ;; list; average of unusable energy

  ;; Assorted measures
  g-geo-Mj                  ;; GeoAve of joint fitness measure all OAMs
  g-geo-Mt                  ;; GeoAve of time fitness measure all OAMs
  g-geo-Eu                  ;; GeoAve of Odum Efficiency measure all OAMs
  g-ttl-age-of-chains       ;; the sum of age of all chains
  g-ttl-dt-of-chains        ;; the sum of discharge time of all chains
  
  ;; Colours
  g-hoam-colour             ;; the default colour for a HOAM
  g-primed-colour           ;; the default colour for a primed HOAM
  gl-colour-pallette        ;; list of allowed colours
  
  ;; OPERATIONAL SWITCHES
  ;; Switch to allow the mass in heads to mutate.
  ;; gb-mutate-heads
  ;; Switch to allow the mass in tails to mutate.
  ;; gb-mutate-tails
  ;; Switch to disable horse-race mode.
  ;; gb-horse-race-on
  
  ;; PLOTS
  ;; Switch for plots
  ;; gb-plots-on              ;; Switch, Native Boolean, enables/disables plotting

  ;; Plot "Age Distribution - Chains"
  ;; Plot "Ln(Mass) Distribution - HOAMs"
  ;; Plot "Ln(Mass) Per HOAM"
  ;; Plot "Ave(Eu) Per OAM"
  ;; Plot "Average Drop Time - Chains"
  ;; Plot "Ave(Aggregated Fitness Measures)"
  
  
  ;; Other - built-in or declared implicitly in plot interface items
  ;; See each plot design dialogue.

  ;;--------------------------
  ;; DATA CAPTURE TO CSV FILES
  ;;--------------------------

  ;; CSV means "Character Separated Values"
  ;; I use a space to separate values.  This can be read by MS Excel.

  g-recno-max        ;; Maximum record number for all files.

  ;; Data Per Xaction
  gb-dpx-on          ;; Numeric Boolean switch
  gs-dpx-status      ;; Interpretation of gb-dpx-on
  gs-dpx-file-name   ;; The file name
  g-dpx-recno        ;; The number of the last record written.

  ;; Data Per Tick
  gb-dpt-on          ;; Numeric Boolean switch
  gs-dpt-status      ;; Interpretation of gb-dpt-on
  gs-dpt-file-name   ;; The file name
  g-dpt-recno        ;; The number of the last record written.

  ;;---------------
  ;; DEBUG CONTROLS
  ;;---------------
  
  gb-debug-on                 ;; Numeric Boolean, opens debug log file, 0 or 1.
  gs-debug-status             ;; for monitor, '1 (On)' or '0 (Off)', 
  ;; gs-debug-step-chooser    ;; Chooser, used with gb-debug-flow-on
  gb-debug-flow-on            ;; Numeric Boolean, in association with chooser, 
  gs-log-file-name            ;; name of the debug log file
                              ;;   opens flow to log file
  ;; gb-debug-show-steps      ;; Switch, Native Boolean, show in command centre
]


;;-----------------------------------------------------------------------------|
;; Attributes of patches
patches-own 
[
  ;; BUILT-IN ATTRIBUTES 
  ;; pxcor        ;; min-pxcor <= pxcor < max-pxcor
  ;; pycor        ;; min-pxcor <= pxcor < max-pxcor 
  ;; pcolor       ;; color of this patch ( 0 <= color < 140 ) 
  ;; plabel       ;; label of this patch
  ;; plabel-color ;; color of this patch's label ( 0 <= label-color < 140 ) 
   
  ;; OamLab-DETERMINED ATTRIBUTES
  ;; Nil.
]

;;-----------------------------------------------------------------------------|
;; Attributes of links
;; nil
;; I don't understand links and did not use any.

;;-----------------------------------------------------------------------------|
;; Turtles and breeds
breed [ heads  head ]
breed [ bodies body ]
breed [ tails  tail ]

;;-----------------------------------------------------------------------------|
;; Attributes of heads
heads-own 
[
  ;; BUILT-IN ATTRIBUTES
  ;; who         ;; fixed id number
  ;; breed       ;; to which breed this turtle belongs [head]
  ;; heading     ;; 0 <= heading < 360, 0 = north
  ;; xcor        ;; min-pxcor <= xcor < max-pxcor
  ;; ycor        ;; min-pxcor <= xcor < max-pxcor
  ;; size        ;; size relative to a patch, default is 1
  ;; shape       ;; a shape chosen from the shape library
  ;; color       ;; color of this turtle ( 0 <= color < 140 )
  ;; pen-mode    ;; "up" or "down"
  ;; pen-size    ;; in pixels
  ;; hidden?     ;; true or false
  ;; label       ;; label of this turtle
  ;; label-color ;; color of this turtle's label ( 0 <= label-color < 140 )
  
  ;; USER-DETERMINED ATTRIBUTES
  ;; Associated with chain.
  mas-sn                   ;; serial number of parent chain.
  chain-sn                 ;; serial number of this chain.
  index-into-chains-lib    ;; the index of this chain in gl-chains-lib
  age-of-chain             ;; age of this chain
  primed-rh-hoam-index     ;; index of active RH-HOAM
  primed-lh-hoam-index     ;; index of active LH-HOAM
  default-colour           ;; as it says
  chain-time-to-drop       ;; total time required to discharge all OAMs
  ;; For these measures, the least fit has the lowest measure.
  Mj-pi-this-chain         ;; product of Mj of chain
  Mt-pi-this-chain         ;; product of Mt of chain
  Eu-pi-this-chain         ;; product of Eu of chain
  Mj-geo-this-chain        ;; GeoAve of Mj of chain
  Mt-geo-this-chain        ;; GeoAve of Mt of chain
  Eu-geo-this-chain        ;; GeoAve of Eu of chain
  fitness-measure          ;; currently active fitness measure

  ;; Associated with HOAM.
  index-into-chain     ;; the serial index (position) of this HOAM
  mass                 ;; the mass in this HOAM

  ;; Associated with rh-hoam.
  oam-time-to-drop     ;; time required for heavy mass to fall
  age-to-discharge     ;; age at which discharge is possible
  energy-to-transfer   ;; amount of high-grade energy to be transferred
  energy-to-discharge  ;; amount of low-grade energy to be exhausted
  Mj-in-oam            ;; Mj is joint fitness measure
  Mt-in-oam            ;; Mt is time fitness measure
  Eu-in-oam            ;; Eu is Odum's efficiency measure
]

;;-----------------------------------------------------------------------------|
;; Attributes of bodies
bodies-own 
[
  ;; BUILT-IN ATTRIBUTES
  ;; who      ;; fixed id number
  ;; breed    ;; to which breed this turtle belongs [body]
  ;; heading  ;; 0 <= heading < 360, 0 = north
  ;; xcor     ;; min-pxcor <= xcor < max-pxcor
  ;; ycor     ;; min-pxcor <= xcor < max-pxcor
  ;; size     ;; size relative to a patch, default is 1
  ;; shape    ;; a shape chosen from the shape library
  ;; color    ;; color of this turtle ( 0 <= color < 140 )
  ;; pen-mode ;; "up" or "down"
  ;; pen-size ;; in pixels
  ;; hidden?  ;; true or false
  ;; label    ;; label of this turtle
  ;; label-color ;; color of this turtle's label ( 0 <= label-color < 140 )
   
  ;; USER-DETERMINED ATTRIBUTES
  ;; Associated with chain.
  ;; Nil.

  ;; Associated with this HOAM.
  index-into-chain     ;; the serial index (position) of this HOAM
  mass                 ;; the mass in this HOAM

  ;; Associated with rh-hoam.
  oam-time-to-drop     ;; time required for heavy mass to fall
  age-to-discharge     ;; age at which discharge is possible
  energy-to-transfer   ;; amount of high-grade energy to be transferred
  energy-to-discharge  ;; amount of low-grade energy to be exhausted
  Mj-in-oam            ;; Mj is joint fitness measure
  Mt-in-oam            ;; Mt is time fitness measure
  Eu-in-oam            ;; Eu is Odum's efficiency measure
]

;;-----------------------------------------------------------------------------|
;; Attributes of tails
tails-own 
[
  ;; BUILT-IN ATTRIBUTES
  ;; who      ;; fixed id number
  ;; breed    ;; to which breed this turtle belongs [tail]
  ;; heading  ;; 0 <= heading < 360, 0 = north
  ;; xcor     ;; min-pxcor <= xcor < max-pxcor
  ;; ycor     ;; min-pxcor <= xcor < max-pxcor
  ;; size     ;; size relative to a patch, default is 1
  ;; shape    ;; a shape chosen from the shape library
  ;; color    ;; color of this turtle ( 0 <= color < 140 )
  ;; pen-mode ;; "up" or "down"
  ;; pen-size ;; in pixels
  ;; hidden?  ;; true or false
  ;; label    ;; label of this turtle
  ;; label-color ;; color of this turtle's label ( 0 <= label-color < 140 )
   
  ;; USER-DETERMINED ATTRIBUTES
  ;; Associated with chain.
  ;; Nil.

  ;; Associated with the HOAM.
  index-into-chain     ;; the serial index (position) of this HOAM
  mass                 ;; the mass in this HOAM

  ;; Associated with rh-hoam.
  ;; Nil.
]

;;-----------------------------------------------------------------------------|
;; SECTION C – INITIALIZATION OR SETUP PROCEDURE( S )
;;-----------------------------------------------------------------------------|

;;-----------------------------------------------------------------------------|
;; The 'autostart' startup routine

to startup
  ;; This routine is to be executed by the observer.

  ;; The manual describes this routine as follows:
  ;; This procedure, if it exists, will be called when a model is first loaded in 
  ;;   the NetLogo application.  Startup does not run when a model is run headless 
  ;;   from the command line, or by parallel BehaviorSpace.

  ;; On loading the model, the debug feature is always off.
  set gb-debug-on 0
  set gs-debug-status "0 (Off)"
  
  ;; On loading the model, the data capture is always off.
  f-close-dpx-file
  f-close-dpt-file
  
  ;; On loading the model, the model, the choosers, switches and sliders are
  ;;   always reset to the values that are known to work.  Only the choosers
  ;;   for the scenario is not reset.  The last saved 
  ;;   selection of scenario is persistant.  This allows the 'Reset Defaults'
  ;;   button to NOT reset the scenario.
  f-reset-default-parameters

  ;; Run the setup routine to initialize other globals.
  setup
  ;; End of startup
end 

;;-----------------------------------------------------------------------------|
;; The setup button(s)

to setup
  ;; This routine is to be executed by the observer.

  ;; NOTE: The contents of switches, sliders, and choosers seem to be 
  ;;   immune to these 'clear' commands.
  clear-ticks
  clear-turtles
  clear-patches
  clear-drawing
  clear-all-plots
  clear-output
  ;; clear-globals   ;; Suppressed to make gb-debug-on value persistent.
  ;; NOTE: Instead of 'clear-globals', you must ensure all globals are 
  ;;   initialized properly in 'setup'.
  
  ;; The version should be coded in this global variable to be included in
  ;;   output files.
  set gs-Version "OamLab_V1.10" 

  ;; Debug features may be off or on depending on history.
  ;;   - Perhaps 'Setup' was called by 'to Startup'.
  ;;   - Perhaps 'setup' was called during a 'BehaviorSpace' run.
  ;;   - Perhaps 'setup' was called by a user-pushed 'setup' button.
  ;; Setup needs to handle some quasi-persistant values correctly regardless of
  ;;   the history.  For gb-debug-on, in particular, I want it to be 
  ;;   persistant so I can have debug output from the 'setup' routine routed
  ;;   to the debug log file, or to the command centre.
  
  ;; 'startup' automatically sets gb-debug-on to 0 when the application is first
  ;;   loaded.  I want to be able to (A) toggle debug on, then, (B) press 
  ;;   'setup' and watch the debug output of the 'setup' command.  The gb-debug-on
  ;;   must be persistant through the above 'clear' commands.  The debug log 
  ;;   file name and status, however, should not be persistent and must be 
  ;;   reset when setup runs, if appropriate.
  ifelse ( gb-debug-on = 1 )
  [
    ;; Debug is on due to user setting, so file name and status should be 
    ;;   reset.  I do this by turn the feature off then on.
    ;; First toggle it off, closing any remnant log file, if needed.
    f-toggle-debug
    ;; Then toggle it back on, opening a new time-stamped log file.
    f-toggle-debug
  ]
  ;; else
  [
    ;; Debug is off, possibly due to startup execution, possibly due to user 
    ;;   choice.
    ;; Ensure associated variables have compatible settings.
    set gb-debug-on 0              ;; Redundant but ensures consistency.
    set gs-debug-status "0 (Off)"  ;; Redundant but ensures consistency.
    set gb-debug-flow-on 0         ;; Step-specific flow is off.
    file-close-all                 ;; Close the debug log file.
    set gs-log-file-name "dummyname"
  ]
  
  ;; Now, do the standard check that is done at the start of each debuggable 
  ;;   routine.  This must follow the clear commands, which reset everything 
  ;;   except globals, switches, sliders and choosers.
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "setup" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Setup: Debug on; tick = " 0 ]
    [ set gb-debug-flow-on 0 ]
  ]

  ;; g-use-this-seed comes from a slider, and is persistant.
  random-seed g-use-this-seed      ;; Tells the PRNG to use this seed.
  
  ;; Data capture to file feature.
  ;;   The data capture files may be open, and the features, stored in switches,
  ;;   may be on, as they are persistent.  Ensure they are off.
  f-close-dpx-file
  f-close-dpt-file
  
  ;; Set the limit on the number of records in a CSV data file.
  ;; This applies to dpx and dpt files. (Debug log files?) 
  set g-recno-max 500000
  
  ;; There are 3 scenarios possible
  set g-scenario-low-e   0         ;; low Odum Efficiency at start
  set g-scenario-high-e  1         ;; high Odum Efficiency at start
  set g-scenario-mixed-e 2         ;; mixed Odum Efficiency at start

  ;; Use the input from the chooser gs-scenario to invoke the selected scenario.
  set g-scenario-number g-scenario-low-e  ;; default
  ifelse( gs-scenario = "Low Eu (Odum Efficiency)" )
  [
    set g-scenario-number g-scenario-low-e
  ]
  ;; else
  [
    ifelse( gs-scenario = "High Eu (Odum Efficiency)" )
    [
      set g-scenario-number g-scenario-high-e
    ]
    ;; else
    [
      ;; gs-scenario = "Mixed Eu (Odum Efficiency)"
      set g-scenario-number g-scenario-mixed-e
    ]
  ]
  
  ;; Special scenario
  set g-set-max-head-size -1 ;; An invalid value, has it's own input box
  
  ;; There are 3 fitness tests possible
  set g-fitness-joint   0         ;; time and energy
  set g-fitness-time    1         ;; time
  set g-fitness-energy  2         ;; energy

  ;; Use the input from the chooser gs-fitness-measure to invoke the selected test.
  set g-fitness-number g-fitness-joint  ;; default
  ifelse( gs-fitness-measure = "Mj - Joint" )
  [
    set g-fitness-number g-fitness-joint
  ]
  ;; else
  [
    ifelse( gs-fitness-measure = "Mt - Minimal Time To Drop" )
    [
      set g-fitness-number g-fitness-time
    ]
    ;; else
    [
      ;; gs-fitness-measure = "Eu - Maximal Useful Energy"
      set g-fitness-number g-fitness-energy
    ]
  ]
  
  ;; For debugging the debug feature!!!  Suppressed now.
  ;; show ( word "SETUP: Debug Is " gb-debug-on )
  ;; show ( word "SETUP: Debug Status Is " gs-debug-status )
  ;; show ( word "SETUP: Step Chooser Is " gs-debug-step-chooser )
  ;; show ( word "SETUP: Flow Control Is " gb-debug-flow-on )

  ;; For debugging the setup procedure, log the values of the globals.
  LOG-TO-FILE ( word "Do-set: Scenario number     - " g-scenario-number ) 
  LOG-TO-FILE ( word "Do-set: Scenario name       - " gs-scenario )
  LOG-TO-FILE ( word "Do-set: Fitness test number - " g-fitness-number ) 
  LOG-TO-FILE ( word "Do-set: Fitness test name   - " gs-fitness-measure )
  LOG-TO-FILE ( word "Do-set: Random seed         - " g-use-this-seed )

  LOG-TO-FILE ( "" )
  LOG-TO-FILE ( "Do-set: STRUCTURAL PARAMETERS (Sliders):" )
  LOG-TO-FILE ( word g-no-of-chains-at-start " - Number of chains on initiation." )
  LOG-TO-FILE ( word g-no-of-chains-max " - Maximum number of chains." )
  LOG-TO-FILE ( word g-length-of-chains " - Length of all chains"  )
  LOG-TO-FILE ( word g-drop-distance " - Distance a mass falls"  )
  LOG-TO-FILE ( word g-acceleration " - Acceleration due to gravity"  )

  ;; Zero the structural measures.
  ;; Operational variable first
  set g-no-of-chains 0
  
  LOG-TO-FILE ( "" )
  LOG-TO-FILE ( "Do-set: CURRENT STATUS INDICATORS:" )
  LOG-TO-FILE ( word g-no-of-chains " - Current number of chains"  )
  
  ;; Zero the data collection variables next.
  set g-no-of-hoams  0
  set g-no-of-heads  0
  set g-no-of-bodies 0
  set g-no-of-tails  0

  set g-max-head-size 0
  set g-min-tail-size 0

  ;; Zero the lists for structural averages.
  set gl-ttl-lg-nrg-per-hoam  ( n-values g-length-of-chains [0.0] )
  set gl-ttl-mass-per-hoam    ( n-values g-length-of-chains [0.0] )
  set gl-ttl-hg-nrg-per-oam   ( n-values ( g-length-of-chains - 1 ) [0.0] )
  set gl-pi-Mj-per-oam        ( n-values ( g-length-of-chains - 1 ) [1.0] )
  set gl-pi-Mt-per-oam        ( n-values ( g-length-of-chains - 1 ) [1.0] )
  set gl-pi-Eu-per-oam        ( n-values ( g-length-of-chains - 1 ) [1.0] )
  set gl-geo-Mj-per-oam       ( n-values ( g-length-of-chains - 1 ) [1.0] )
  set gl-geo-Mt-per-oam       ( n-values ( g-length-of-chains - 1 ) [1.0] )
  set gl-geo-Eu-per-oam       ( n-values ( g-length-of-chains - 1 ) [1.0] )

  ;; Zero the per tick throughput measures.
  set gl-ttl-hg-nrg-per-tick  ( n-values g-length-of-chains [0.0] )
  set gl-ttl-lg-nrg-per-tick  ( n-values g-length-of-chains [0.0] )

  ;; Zero other assorted measures.
  set g-geo-Mj 0   ;; Joint fitness measure, all chains
  set g-geo-Mt 0   ;; Time fitness measure, all chains
  set g-geo-Eu 0   ;; Odum Efficiency measure, all chains
  set g-ttl-age-of-chains 0
  set g-ttl-dt-of-chains 0  ;; Drop time, all chains
  
  ;; Colours
  set g-hoam-colour 95     ;; the default colour for a HOAM
  set g-primed-colour 45   ;; the default colour for a primed HOAM
  set gl-Colour-Pallette [5 15 25 35 55 75 85 95 105 115 125 135]
  ;; Note: colour 65 (lime) is used for the background, and has been elided here.
  ;; Note: colour 45 (yellow) is used for primed haoms, and has been elided here.
  
  ;; The main lists.
  set gl-new-chain []      ;; construction site of new chains of turtles
  set gl-chains-lib []     ;; library of current chains of hoams
  set gl-chains-indices [] ;; indices of unfit chains
  set g-next-chain-sn 0    ;; Serial number of the next chain
  
  ;; Turn on the mutating heads function.
  ;; set gb-mutate-heads true
  ;; Turn on the mutating tails function.
  ;; set gb-mutate-tails true
  ;; Disable the horse race mode.
  ;; set gb-horse-race-on false
  
  ;; Turn on the plotting function.
  ;; Default is 'on'.
  set gb-plots-on true
  
  set-default-shape heads  "face happy"  ;; pulled from shapes library
  set-default-shape bodies "circle"      ;; pulled from shapes library
  set-default-shape tails  "circle"      ;; pulled from shapes library

  ask patches 
  [ 
    set pcolor lime
  ]
   
  f-build-initialized-chains

  ;; Aggregates.
  ;; The aggregates must be updated after the chains are built.
  ;; The aggregates must be updated before any plots are invoked.
  f-update-aggregates  ;; Totals and averages.
    
  reset-ticks      ;; restarts tick counter and runs setup commands within plots

  ;; This call requires that 'reset-ticks' be called first.
  f-compute-energetics-of-chains
  ;; Update the aggregates again, after energetics computed.
  f-update-aggregates  ;; Totals and averages.

  ;; Clears unwanted zeros in plots.
  clear-all-plots
  setup-plots
  
  ;; Debug controls
  set gb-debug-flow-on 0 ;; Boolean, in association with chooser, turns debug LOG-TO-FILE on/off
  set g-halt-at-tick -1  ;; input variable to set a tick for stopping

  LOG-TO-FILE "Do-set: procedure completed" 

  ;; End of setup
end 

;;-----------------------------------------------------------------------------|
;; Initialize a set of chains.

to f-build-initialized-chains
  ;; This routine is to be executed by the observer.

  ;; g-no-of-chains is initialized in to Setup.
  while [ g-no-of-chains < g-no-of-chains-at-start ]
  [
    LOG-TO-FILE ( word "  Initializing: Chain " g-no-of-chains )
    f-build-initialized-chain
    
    ;; g-no-of-chains is incremented in f-build-initialized-chain.
    ;; Give the new chain a serial number.
    let this-chain-index ( g-no-of-chains - 1 )
    let this-chain ( item this-chain-index gl-chains-lib )
    let this-head ( item 0 this-chain )
    ask this-head
    [
      set chain-sn ( g-next-chain-sn )
      set g-next-chain-sn ( g-next-chain-sn + 1 )
      set mas-sn -1  ;; These chains have no parent.
    ]
  ] 
  
  ;; end f-build-initial-chains
end 

;;-----------------------------------------------------------------------------|
;; Build an initialized chain.

to f-build-initialized-chain
  ;; This routine is to be executed by the observer.

  ;; Create a new chain near the origin in the global variable.
  f-populate-gl-new-chain
  
  f-add-new-chain-to-chains-lib
  
  ;; end f-build-initialized-chain
end 

;;-----------------------------------------------------------------------------|
;; Add chain to library and move into arena.

to f-add-new-chain-to-chains-lib
  ;; This routine is to be executed by the observer.

  ;; Move this chain into place in the arena.  Does not put turtles in lib.
  f-relocate-this-chain gl-new-chain
  
  ;; Mark this chain with an index into gl-chains-lib.
  let head ( item 0 gl-new-chain )
  ask head
  [
    set index-into-chains-lib g-no-of-chains
  ]
  
  set gl-chains-lib ( lput gl-new-chain gl-chains-lib )
  
  ;; Increment the counter.
  set g-no-of-chains ( g-no-of-chains + 1 )
  
  set gl-new-chain []  
  ;; End of f-add-new-chain-to-chains-lib
end 

;;-----------------------------------------------------------------------------|
;; Initialize a single chain.

to f-populate-gl-new-chain
  ;; This routine is to be executed by the observer.

  LOG-TO-FILE ( word "    Initializing in gl-new-chain" )
  ;; Start with the head.
  let this-colour 45
  let this-patch patch 0 0
  ask this-patch 
  [ 
    sprout-heads 1 
    [ 
      set default-colour ( one-of gl-colour-pallette )
      set this-colour default-colour
    ]
  ] 
  let this-head heads-on this-patch
  set gl-new-chain ( list this-head )
  ask this-head 
  [ 
    f-initialize-new-head  
    set index-into-chain 0
  ]  ;; Initialize and move it out of the road.
  set g-no-of-heads ( g-no-of-heads + 1 )
  set g-no-of-hoams ( g-no-of-hoams + 1 )
  LOG-TO-FILE ( word "      Head initialized: HOAM 0" )
    
  ;; Add the body parts.
  let this-hoam-index 1  ;; half open Atwood's Machine
  while [ this-hoam-index < ( g-length-of-chains - 1 ) ]
  [
    ask this-patch [ sprout-bodies 1 [ set color this-colour ] ] 
    let this-body bodies-on this-patch
    ask this-body  
    [ 
      f-initialize-new-body 
      set index-into-chain this-hoam-index
    ]
    set gl-new-chain ( lput this-body gl-new-chain )  ;; add to end of chain
    set g-no-of-bodies ( g-no-of-bodies + 1 )
    set g-no-of-hoams ( g-no-of-hoams + 1 )

    LOG-TO-FILE ( word "      Body initialized: HOAM " this-hoam-index )
    set this-hoam-index ( this-hoam-index + 1 )
  ]

  ;; End with the tail.
  ask this-patch [ sprout-tails 1 [ set color this-colour ] ] 
  let this-tail tails-on this-patch
  ask this-tail 
  [ 
    f-initialize-new-tail 
    set index-into-chain ( g-length-of-chains - 1 )  ;; an index
  ]
  set gl-new-chain ( lput this-tail gl-new-chain )  ;; add to end of chain
  set g-no-of-tails ( g-no-of-tails + 1 )
  set g-no-of-hoams ( g-no-of-hoams + 1 )
  LOG-TO-FILE ( word "      Tail initialized: HOAM " ( g-length-of-chains - 1 ) )
  
  ;; The parts are now all in place in the list.
  ;; Adjust masses and compute efficiencies.
  LOG-TO-FILE ( word "    Efficiencies being adjusted: Scenario no " g-scenario-number )
  ifelse ( g-scenario-number = g-scenario-low-e )
  [
    f-assign-low-e-to-new-chain gl-new-chain
  ]
  ;; else
  [
    ifelse ( g-scenario-number = g-scenario-high-e )
    [
      f-assign-high-e-to-new-chain gl-new-chain
    ]
    ;; else
    [
      ;; g-scenario-number = g-scenario-mixed-e
      f-assign-mixed-e-to-new-chain gl-new-chain
    ]
  ]
  
  ;; end f-populate-gl-new-chain
end 

;;-----------------------------------------------------------------------------|
;; Initialize a single head.

to f-initialize-new-head
  ;; This routine is to be executed by a head.

  ;; BUILT-IN ATTRIBUTES
  ;; who         ;; set automatically
  set heading 90 ;; east
  ;; xcor        ;; min-pxcor <= xcor < max-pxcor
  ;; ycor        ;; min-pxcor <= xcor < max-pxcor
  ;; pen-mode    ;; "up" or "down"
  ;; pen-size    ;; in pixels
  ;; size        ;; size relative to a patch, default is 1

  ;; USER-DETERMINED ATTRIBUTES
  ;; Associated with chain.
  set mas-sn -1                 ;; serial number of parent chain
  set chain-sn -1               ;; serial number of parent chain
  set index-into-chains-lib -1  ;; index of this chain in gl-chains-lib
  set age-of-chain 0            ;; age of this chain
  set primed-rh-hoam-index 0    ;; index of active RH-HOAM
  set primed-lh-hoam-index 0    ;; index of active LH-HOAM
  set chain-time-to-drop 0      ;; total time for chain to discharge all OAMs.

  set Mj-pi-this-chain       1  ;; product of Mj across chain
  set Mt-pi-this-chain       1  ;; product of Mt across chain
  set Eu-pi-this-chain       1  ;; product of Eu across chain
  set Mj-geo-this-chain      1  ;; geometric average Mj of chain
  set Mt-geo-this-chain      1  ;; geometric average Mt of chain
  set Eu-geo-this-chain      1  ;; geometric average Eu of chain
  set fitness-measure        1  ;; active fitness-measure

  ;; Associated with HOAM.
  set index-into-chain 0     ;; the serial position
  set mass 16                ;; the mass in this HOAM

  ;; Associated with rh-hoam.
  set oam-time-to-drop 0     ;; time required for heavy mass to fall
  set age-to-discharge  -1   ;; next tick at which discharge is possible
  set energy-to-transfer 0   ;; amount of high-grade energy to be transferred
  set energy-to-discharge  0 ;; amount of low-grade energy to be exhausted
  set Mt-in-oam 1            ;; Mt is time fitness measure
  set Eu-in-oam 1            ;; Eu is Odum's efficiency measure
  set Mj-in-oam 1            ;; Mj is joint fitness measure
  
  forward 1  ;; Move it out of the road.
  ;; end f-initialize-new-head
end 

;;-----------------------------------------------------------------------------|
;; Initialize a single body element.

to f-initialize-new-body
  ;; This routine is to be executed by a body.

  ;; BUILT-IN ATTRIBUTES
  ;; who        ;; set automatically
  set heading 90 ;; east
  ;; xcor       ;; min-pxcor <= xcor < max-pxcor
  ;; ycor       ;; min-pxcor <= xcor < max-pxcor
  ;; pen-mode   ;; "up" or "down"
  ;; pen-size   ;; in pixels
  ;; size       ;; size relative to a patch, default is 1

  ;; USER-DETERMINED ATTRIBUTES
  ;; Associated with HOAM.
  ;; set index-into-chain 1  ;; the serial position
  set mass 16                ;; the mass in this HOAM

  ;; Associated with rh-hoam.
  set oam-time-to-drop 0     ;; time required for heavy mass to fall
  set age-to-discharge -1    ;; next tick at which discharge is possible
  set energy-to-transfer 0   ;; amount of high-grade energy to be transferred
  set energy-to-discharge 0  ;; amount of low-grade energy to be exhausted
  set Mt-in-oam 1            ;; Mt is time fitness measure
  set Eu-in-oam 1            ;; Eu is Odum's efficiency measure
  set Mj-in-oam 1            ;; Mj is joint fitness measure
 
  forward 1  ;; Move it out of the road.
  ;; end f-initialize-new-body
end 

;;-----------------------------------------------------------------------------|
;; Initialize a single tail.

to f-initialize-new-tail
  ;; This routine is to be executed by a tail.

  ;; BUILT-IN ATTRIBUTES
  ;; who        ;; set automatically
  set heading 90 ;; east
  ;; xcor       ;; min-pxcor <= xcor < max-pxcor
  ;; ycor       ;; min-pxcor <= xcor < max-pxcor
  ;; pen-mode   ;; "up" or "down"
  ;; pen-size   ;; in pixels
  ;; size       ;; size relative to a patch, default is 1

  ;; USER-DETERMINED ATTRIBUTES
  ;; Associated with HOAM.
  ;; set index-into-chain 1  ;; the serial position
  set mass 16                ;; the mass in this HOAM
  
  forward 1  ;; Move it out of the road.
  ;; end f-initialize-new-tail
end 

;;-----------------------------------------------------------------------------|
;; Initialize the masses and efficiencies - low e.

to f-assign-low-e-to-new-chain [ to-this-chain ]
  ;; This routine is to be executed by the observer.
  
  ;; This does not alter the mass in the tail.
  ;; For low efficiencies, the heavy mass must be substantially larger. 
  let this-lhhoam-index ( g-length-of-chains - 1 )  ;; half open Atwood's Machine
  while [ this-lhhoam-index > 0 ] 
  [
    let this-lhhoam ( item this-lhhoam-index to-this-chain ) ;; target the lh-HOAM.
    let next-rhhoam ( item ( this-lhhoam-index - 1 ) to-this-chain ) ;; target the rh-HOAM.
    
    let light-mass ( item 0 [mass] of this-lhhoam )
    let heavy-mass ( light-mass / 0.10 )
    let this-Eu ( light-mass / heavy-mass )
    let mass-total ( heavy-mass + light-mass )
    let mass-diff  ( heavy-mass - light-mass )
    let this-Mt ( ( mass-diff / mass-total ) ^ ( 0.5 ) )
    let this-Mj ( this-Mt * this-Eu )
    
    ask next-rhhoam 
    [ 
      set mass heavy-mass
      set Mt-in-oam this-Mt  ;; Time fitness measure
      set Eu-in-oam this-Eu  ;; Odum Efficiency measure 
      set Mj-in-oam this-Mj  ;; Joint fitness measure
    ]
    
    LOG-TO-FILE ( word "      Low-e: HOAM " ( this-lhhoam-index - 1 ) "; mass: " heavy-mass )
    set this-lhhoam-index ( this-lhhoam-index - 1 )
  ]
  
  ;; end of f-assign-low-e-to-new-chain
end 

;;-----------------------------------------------------------------------------|
;; Initialize the masses and efficiencies - high e.

to f-assign-high-e-to-new-chain [ to-this-chain ]
  ;; This routine is to be executed by the observer.

  ;; This does not alter the mass in the tail.
  ;; For high efficiencies, the heavy mass must be slightly larger. 
  let this-lhhoam-index ( g-length-of-chains - 1 )  ;; half open Atwood's Machine
  while [ this-lhhoam-index > 0 ] 
  [
    let this-lhhoam ( item this-lhhoam-index to-this-chain ) ;; target the lh-hoam.
    let next-rhhoam ( item ( this-lhhoam-index - 1 ) to-this-chain ) ;; target the rh-hoam.
    
    let light-mass ( item 0 [mass] of this-lhhoam )
    let heavy-mass ( light-mass / 0.90 )
    let this-Eu ( light-mass / heavy-mass )
    let mass-total ( heavy-mass + light-mass )
    let mass-diff  ( heavy-mass - light-mass )
    let this-Mt ( ( mass-diff / mass-total ) ^ ( 0.5 ) )
    let this-Mj ( this-Mt * this-Eu )
    
    ask next-rhhoam 
    [ 
      set mass heavy-mass
      set Mt-in-oam this-Mt  ;; Time fitness measure
      set Eu-in-oam this-Eu  ;; Odum Efficiency measure 
      set Mj-in-oam this-Mj  ;; Joint fitness measure
    ]
    
    LOG-TO-FILE ( word "      High-e: HOAM " ( this-lhhoam-index - 1 ) "; mass: " heavy-mass )
    set this-lhhoam-index ( this-lhhoam-index - 1 )
  ]

  ;; end of f-assign-high-e-to-new-chain
end 

;;-----------------------------------------------------------------------------|
;; Initialize the masses and efficiencies - mixed e.

to f-assign-mixed-e-to-new-chain [ to-this-chain ]
  ;; This routine is to be executed by the observer.

  ;; This does not alter the mass in the tail.
  ;; For variable efficiencies, the heavy mass must be variably larger. 
  let this-lhhoam-index ( g-length-of-chains - 1 )  ;; half open Atwood's Machine
  while [ this-lhhoam-index > 0 ] 
  [
    let this-lhhoam ( item this-lhhoam-index to-this-chain ) ;; target the lh-HOAM.
    let next-rhhoam ( item ( this-lhhoam-index - 1 ) to-this-chain ) ;; target the rh-HOAM.
    
    let random-efficiency ( ( random-float 1 ) * 0.8 ) ;; [ 0, 0.8 )
    set random-efficiency 0.10 + random-efficiency   ;; [ 0.10, 0.90 )
    
    let light-mass ( item 0 [mass] of this-lhhoam )
    let heavy-mass ( light-mass / random-efficiency )
    let this-Eu ( light-mass / heavy-mass )
    let mass-total ( heavy-mass + light-mass )
    let mass-diff  ( heavy-mass - light-mass )
    let this-Mt ( ( mass-diff / mass-total ) ^ ( 0.5 ) )
    let this-Mj ( this-Mt * this-Eu )
    
    ask next-rhhoam 
    [ 
      set mass heavy-mass
      set Mt-in-oam this-Mt  ;; Time fitness measure
      set Eu-in-oam this-Eu  ;; Odum Efficiency measure
      set Mj-in-oam this-Mj  ;; Joint fitness measure
    ]
    
    LOG-TO-FILE ( word "      Mixed-e: HOAM " ( this-lhhoam-index - 1 ) "; mass: " heavy-mass )
    set this-lhhoam-index ( this-lhhoam-index - 1 )
  ]

  ;; end of f-assign-mixed-e-to-new-chain
end 


;;-----------------------------------------------------------------------------|
;; Move the chain from where it was built to where you want it to appear.

to f-relocate-this-chain [ chain-to-relocate ]
  ;; This routine is to be executed by the observer.

  ;; Move this chain into place in the arena.
  ;; This moves the display into place, according to the index stored in the
  ;;   head, and does not affect its location in memory.
  let this-hoam-index 0
  while [ this-hoam-index < g-length-of-chains ]
  [
    let this-hoam ( item this-hoam-index gl-new-chain )
    ask this-hoam
    [
      set xcor ( max-pxcor - ( this-hoam-index + 1 ) )
      set ycor ( g-no-of-chains + 1 )
    ]
    set this-hoam-index ( this-hoam-index + 1 )
  ]
  LOG-TO-FILE ( word "  Relocated to: xcor: " 
    ( max-pxcor - 1 ) "; ycor: " ( g-no-of-chains + 1 ) )
  
  ;; End of f-relocate-this-chain [ chain-to-relocate ]
end 

;;-----------------------------------------------------------------------------|
;; Compute the energy changes, Odum Efficiency, and time to drop for this OAM.

to f-compute-energetics-of-chains
  ;; This routine is to be executed by the observer.

  let chain-index 0
  let this-chain gl-new-chain
  while [ chain-index < g-no-of-chains ]
  [
    set this-chain ( item chain-index gl-chains-lib )
    
    LOG-TO-FILE ( word "Computing Energetics: Chain " chain-index )
    f-compute-energetics-of-chain this-chain
  
    ;; And, prime the first OAM in the chain.
    ;; Each possible OAM in the chain was actually primed in the above
    ;;   call, from a programming point of view, but metaphorically, it
    ;;   is not primed until the previous OAM has discharged its energy.
    f-prime-oam 0 1 this-chain
    
    set chain-index ( chain-index + 1 )
  ]
  ;; End of f-compute-energetics-of-chains
end 

;;-----------------------------------------------------------------------------|
;; Compute the energy changes, Odum Efficiency, and time to drop for this OAM.

to f-compute-energetics-of-chain [ of-this-chain ]
  ;; This routine is to be executed by the observer.

  ;; Compute energetics for all OAMs in the chain.  An OAM is composed of
  ;;   an LH-HOAM linked to a RH-HOAM.  'Energetics' includes:
  ;;   - energy to be transferred from RH-HOAM to LH-HOAM
  ;;   - energy to be exhausted from RH-HOAM
  ;;   - oam-time-to-drop for RH-HOAM
  ;;   - accumulated time-to-discharge for RH-HOAM, across chain
  ;;   - three local measures associated with each RH-HOAM:
  ;;     - Mj - joint fitness measure for time and energy = Mt*Eu
  ;;     - Mt - fitness measure of time used = Td/Tb
  ;;     - Eu - Odum's efficiency measure of used energy = Ml/Mh
  ;;
  ;; These are rolled up to compute four indices for the chain as a whole:
  ;;   - Geometric average of the Mjs - the joint fitness measure
  ;;   - Geometric average of the Mts - the time fitness measure
  ;;   - Geometric average of the Eus - Odum Efficiency fitness measure
  ;;   
  
  ;; The masses (and efficiencies) were set in the 'f-asign- routine(s).
  ;; Time-to-discharge is tricky.  Often it is a non-integer, and so
  ;;   the next OAM is constituted and released at some time before
  ;;   the current tick started.  Each time-to-discharge needs to
  ;;   be computed from the initial release of OAM 0.
  let total-time-to-drop 0
  
  let this-head ( item 0 of-this-chain )
  let this-colour ( item 0 [default-colour] of this-head )
  let chain-index ( item 0 [index-into-chains-lib] of this-head )
  let sn-of-chain ( item 0 [chain-sn] of this-head )
  let this-pi-Mj 1
  let this-pi-Mt 1
  let this-pi-Eu 1
  
  let rhhoam-index 0
  ;; Only index for rh-hoams.  Leave out the tail.
  while [ rhhoam-index < ( g-length-of-chains - 1 ) ]
  [
    ;; Compute values within OAM (linking pairs of HOAMs).
    LOG-TO-FILE ( word "  Comp Energetics: Ch(" sn-of-chain "," 
      chain-index "); OAM " rhhoam-index )
    set total-time-to-drop 
      fr-compute-energetics-of-oam rhhoam-index total-time-to-drop of-this-chain
    
    ;; Access the RH-HOAM of this HOAM pair, this OAM.
    let this-hoam ( item rhhoam-index of-this-chain )
    ;; While here, I do a little non-relevant house-cleaning.
    ask this-hoam [ set color this-colour ]
    
    ;; Multiply the efficiencies, as basis for geometric average.
    set this-pi-Mj ( this-pi-Mj * ( item 0 [Mj-in-oam] of this-hoam ) )
    set this-pi-Mt ( this-pi-Mt * ( item 0 [Mt-in-oam] of this-hoam ) )
    set this-pi-Eu ( this-pi-Eu * ( item 0 [Eu-in-oam] of this-hoam ) )
    
    set rhhoam-index ( rhhoam-index + 1 )
  ]

  ;; Store the total time to drop in the head.
  ask this-head [ set chain-time-to-drop total-time-to-drop ]
  
  ;; Determine the correct root to use.
  let proper-root ( 1 / ( g-length-of-chains - 1 ) ) ;; 1 / (Number of OAMs).

  ;; Compute the geometric average of Mj across the chain of HOAMs.
  ;; This is based on Mj = Eu * Mt
  let this-geo-ave-Mj ( this-pi-Mj ^ proper-root )
  ask this-head 
  [ 
    set Mj-pi-this-chain this-pi-Mj 
    set Mj-geo-this-chain this-geo-ave-Mj 
  ]
  LOG-TO-FILE ( word "  CompEn: Joint Fitness Measure  (GeoAveMj) - Mj = " this-geo-ave-Mj )

  ;; Compute the geometric average of Mt across the chain of HOAMs.
  ;; This is based on ( constrained time to drop ) / ( unconstrained time to drop )
  let this-geo-ave-Mt ( this-pi-Mt ^ proper-root )
  ask this-head 
  [ 
    set Mt-pi-this-chain this-pi-Mt 
    set Mt-geo-this-chain this-geo-ave-Mt 
  ]
  LOG-TO-FILE ( word "  CompEn: Time Fitness Measure   (GeoAveMt) - Mt = " this-geo-ave-Mt )

  ;; Compute the geometric average of Eu across the chain of HOAMs.
  ;; This is based on Mu = Eu
  let this-geo-ave-Eu ( this-pi-Eu ^ proper-root )
  ask this-head 
  [ 
    set Eu-pi-this-chain this-pi-Eu 
    set Eu-geo-this-chain this-geo-ave-Eu 
  ]
  LOG-TO-FILE ( word "  CompEn: Energy Fitness Measure (GeoAveEu) - Eu = " this-geo-ave-Eu )

  ;; Assign the active fitness measure.
  if( g-fitness-number = 0 ) [ ask this-head [ set fitness-measure Mj-geo-this-chain ] ]
  if( g-fitness-number = 1 ) [ ask this-head [ set fitness-measure Mt-geo-this-chain ] ]
  if( g-fitness-number = 2 ) [ ask this-head [ set fitness-measure Eu-geo-this-chain ] ]
  
  let this-tail ( item ( g-length-of-chains - 1 ) of-this-chain )
  ask this-tail [ set color this-colour ]
  ;; End of f-compute-energetics-of-chain [ of-this-chain ]
end 

;;-----------------------------------------------------------------------------|
;; Compute the energy changes, Odum Efficiency, and time to drop for this OAM.

to-report fr-compute-energetics-of-oam [ rh-hoam-index ttl-time-to-drop in-this-chain ]
  ;; This routine is to be executed by the observer.

  let lh-hoam-index ( rh-hoam-index + 1 )
  
  let rh-hoam ( item rh-hoam-index in-this-chain )
  let lh-hoam ( item lh-hoam-index in-this-chain )
  
  let mass-heavy item 0 ( [mass] of rh-hoam )
  let mass-light item 0 ( [mass] of lh-hoam )
  let mass-total ( mass-heavy + mass-light )
  let mass-diff  ( mass-heavy - mass-light )

  let this-Eu ( mass-light / mass-heavy )
  let this-Mt ( ( mass-diff / mass-total ) ^ 0.5 )
  let this-Mj ( this-Mt * this-Eu )
  
  let numerator ( 2 * g-drop-distance * mass-total )
  let denominator ( g-acceleration * mass-diff )
  
  let time-to-fall ( ( numerator / denominator ) ^ 0.5 )
  set ttl-time-to-drop ( ttl-time-to-drop + time-to-fall )

  let energy-total   ( g-drop-distance * g-acceleration * mass-heavy )
  let energy-kinetic ( g-drop-distance * g-acceleration * mass-diff )
  let energy-xferred ( energy-total - energy-kinetic )
  
  ask rh-hoam
  [
    set oam-time-to-drop time-to-fall
    set age-to-discharge ttl-time-to-drop
    set Mt-in-oam this-Mt
    set Eu-in-oam this-Eu
    set Mj-in-oam this-Mj
    set energy-to-transfer energy-xferred
    set energy-to-discharge energy-kinetic
  ]
  
  LOG-TO-FILE ( word "  CompEn: oam-time-to-drop    - " time-to-fall )
  LOG-TO-FILE ( word "  CompEn: age-to-discharge    - " ttl-time-to-drop )
  LOG-TO-FILE ( word "  CompEn: Mj-in-oam           - " this-Mj )
  LOG-TO-FILE ( word "  CompEn: Mt-in-oam           - " this-Mt )
  LOG-TO-FILE ( word "  CompEn: Eu-in-oam           - " this-Eu )
  LOG-TO-FILE ( word "  CompEn: energy-to-transfer  - " energy-xferred )
  LOG-TO-FILE ( word "  CompEn: energy-to-discharge - " energy-kinetic )

  report ttl-time-to-drop
  ;; End of fr-compute-energetics-of-oam
end 

;;-----------------------------------------------------------------------------|
;; Indicate which OAM in the HOAM chain is primed.

to f-prime-oam [ rh-hoam-index lh-hoam-index in-this-chain ]
  ;; This routine is to be executed by the observer.

  ASSERT( rh-hoam-index < lh-hoam-index ) ( word "Set: rh-hoam-index = " rh-hoam-index " " ) -1
  ASSERT( lh-hoam-index < ( g-length-of-chains ) ) ( word "Set: rh-hoam-index = " rh-hoam-index " " ) -1
  
  let this-head ( item 0 in-this-chain )
  let this-colour 45 ;; a dummy declaration.
  ask this-head
  [
    ;; Unpack indices.
    let old-rh-hoam-index primed-rh-hoam-index
    let old-lh-hoam-index primed-lh-hoam-index
    set this-colour default-colour
    
    ;; Change colour.
    let this-hoam ( item old-rh-hoam-index in-this-chain )
    ask this-hoam [ set color this-colour ]
    
    ;; Change colour.
    set this-hoam ( item old-lh-hoam-index in-this-chain )
    ask this-hoam [ set color this-colour ]
    
    ;; Change colour.
    set this-hoam ( item rh-hoam-index in-this-chain )
    ask this-hoam [ set color g-primed-colour ]
    
    ;; Change colour.
    set this-hoam ( item lh-hoam-index in-this-chain )
    ask this-hoam [ set color g-primed-colour ]
    
    set primed-rh-hoam-index rh-hoam-index
    set primed-lh-hoam-index lh-hoam-index
  ]
  
  ;; End of f-prime-oam [ rh-hoam-index lh-hoam-index in-this-chain ]
end 

;;-----------------------------------------------------------------------------|
;; Reset the default values for the interface-declared items.

to f-reset-default-parameters 
  ;; The observer executes this routine.

  ;; Switches, sliders and choosers implicitly declare global variables.  The
  ;;   values in these variables are parameters for the model, and many 
  ;;   combinations of those parameters are not sustainable.  However, the
  ;;   values in those user interface devices are stored with the model and
  ;;   are persistant across a save/load action.  The default values must
  ;;   be reset on load, or available to a user as a parameter set.  The
  ;;   purpose of this routine is to store at least one viable set of 
  ;;   parameter values.
  
  ;; Parameters needed for "Setup" routine.
  ;; Initialize the fitness test chooser.
  set gs-fitness-measure "Mj - Joint"
  ;; The chooser that selects between the three scenarios is allowed to be 
  ;;   persistant.  It is not reset here.  This gives the user the ability
  ;;   to choose the scenario for which the defaults are to be restored.
  ;; Initialize the Pseudo Random Number Generator (PRNG).
  set g-use-this-seed 7

  ;; Operational controls, can be changed during a run.
  set gb-plots-on true
  set gb-mutate-heads true
  set gb-mutate-tails true
  set gb-horse-race-on true
   
  ;;-----------------------------------------------
  ;; BIOPHYSICAL SUB-SYSTEM CONTROLS AND PARAMETERS
  ;;-----------------------------------------------

  ;; Structural controls needed for "Setup"
  ;; Slider range settings are shown as (Min,Increment,Max)
  set g-no-of-chains-at-start 30 ;; (  1, 15,   100 ) Chains
  set g-no-of-chains-max 30      
  set g-length-of-chains 14      ;; (  3,  1,    14 ) HOAMs
  set g-drop-distance 100        ;; ( 50,  5,   200 ) meters
  set g-acceleration 10          ;; (  8,  0.10, 12 ) m/s/s
  
  ;; End of f-reset-default-parameters
end 

;;-----------------------------------------------------------------------------|
;; SECTION D – GO OR MAIN-LOOP PROCEDURE( S )
;;-----------------------------------------------------------------------------|

;;-----------------------------------------------------------------------------|
;; The go button

to go
  ;; This routine is to be executed by the observer.

  ;; Stop codes:
  ;; All stop decisions must be here in the 'go' procedure, as it causes an
  ;;   exit from the current procdure only.

  if( g-halt-at-tick = ticks  ) 
  [
    set g-halt-at-tick -1
    stop
  ]
  
  let b-should-stop-now false
  if( count turtles <= 0 ) [ set b-should-stop-now true ]
  if( b-should-stop-now = true )
  [
    f-close-dpx-file
    f-close-dpt-file
    ;; The Debug log file is handled differently elsewhere.
    stop
  ]

  ;; MANUAL CHANGE FOR DEBUG
  ;; If needed, each check for validity can be enabled between steps.
  ;; They have been suppressed (turned into comments) for the sake 
  ;;   of speed of execution, but can be re-enabled if a bug has 
  ;;   somehow been re-introduced.
  ;; A single call to the validity check has been left active inside of the
  ;;   Do-Post-Tick step.  If it flags a problem, re-activate these to
  ;;   narrow down where the problem starts.
  
  ;; Major steps or functions, done once per tick, in order of execution.
  do-pre-tick
  ;; if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test: Do-pre." ) ]

  do-check-chains
  ;; if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test: Do-chk." ) ]

  do-post-tick
  ;; if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test: Do-pos." ) ]

  ;; End of to go
end 

;;-----------------------------------------------------------------------------|
;; D1 - do-pre-tick procedure( s )
;;-----------------------------------------------------------------------------|

to do-pre-tick
  ;; This routine is to be executed by the observer.
  
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "pre-tick" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-Pre-tick: Debug on.; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; Enter all commands that need to be done before a tick begins.
  ;; Supressed. f-update-aggregates
  
  ;; Advance the tick counter by 1 tick.
  ifelse( gb-plots-on = true )
  [
    ;; Advance the ticks by one and update the plots.
    tick
    ;; 'tick' is exactly the same as 'update-plots' except that the tick counter 
    ;;   is incremented before the plot commands are executed.
    
  ]
  ;; else
  [
    ;; Advance ticks by one but do not update the plots.
    tick-advance 1
  ]

  ;; Check to see if dpx file is full.
  if( gb-dpx-on = 1 )
  [
    if( g-dpx-recno > g-recno-max )
    [
      f-reopen-dpx-file
    ]
  ]
  
  ;; Ensure that the derived parameters are properly valued.
  ;; THESE ARE PLACED HERE TO MAKE BEHAVIOUR SPACE (BS) WORKS CORRECTLY.
  ;; BS ADJUSTS THE SLIDERS, BUT THESE ARE DERIVED THEREFROM. 
  ;; Nil changes required.

  ask heads [ set age-of-chain ( age-of-chain + 1 ) ]
  
  ;; Plot "Usage Rates Per Tick"
  ;; Zero the per tick throughput measures.
  set gl-ttl-hg-nrg-per-tick  ( n-values g-length-of-chains [0.0] )
  set gl-ttl-lg-nrg-per-tick  ( n-values g-length-of-chains [0.0] )

  LOG-TO-FILE ( word "Do-pre: Halt at tick - " g-halt-at-tick "; current ticks - " ticks ) 

  LOG-TO-FILE "Do-pre: routine completed."
  ;; End of to do-pre-tick
end 

;;-----------------------------------------------------------------------------|
;; D2 – check-chains procedure(s)
;;-----------------------------------------------------------------------------|

to do-check-chains
  ;; This routine is to be executed by the observer.
  
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "check-chains" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-check-chains: Debug on; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ifelse (gb-horse-race-on = true )
  [
    ;; This is 'horse race' mode.  I thought it would help the visualization
    ;;   of the model if I could 'see' the OAMs form and drop, so I coloured the
    ;;   active OAMs yellow.  It gives the effect of horses racing for the 
    ;;   finish line, and it is relatively dramatic.  A chain replicates when it
    ;;   has finished its drop, so drop time affects how often a chain can 
    ;;   replicate, even when the 'time fitness measure' is not being used.  I am
    ;;   concerned that this distorts the results.  So, I have left this 
    ;;   original version of the horse race as an option.  It is cute.  But, for
    ;;   more serious study of the MPP one should toggle the horse race mode
    ;;   off.
    
    ;; Initialize the list of chains, for this pass of the 'do-check-chains' routine.
    set gl-chains-indices ( [index-into-chains-lib] of heads )
    
    let chains-index fr-get-random-chains-index
    while [ chains-index != -1 ]
    [
      let this-chain ( item chains-index gl-chains-lib )
      let this-chain-sn ( item 0 [chain-sn] of ( item 0 this-chain ) )
      LOG-TO-FILE ( word "Chk Chain (S/N, index): Ch(" this-chain-sn "," chains-index ") " )
      f-check-one-chain-hrmode-on this-chain
      
      set chains-index fr-get-random-chains-index
    ]
  ]
  ;; Else
  [
    ;; This is the mode of operation when 'horse race mode' is turned off.
    
    ;; Initialize the list of chains, for this pass of the 'do-check-chains' 
    ;;   routine.
    ;; Re-initialize the global list again as an empty list.
    set gl-chains-indices []
    ;; Create a temporary list of heads sorted in descending order of fitness.
    let temp-list ( sort-on [(- fitness-measure)] heads )
    foreach temp-list 
    [ 
      ;; Add each index to the list, in descending order of fitness.
      ask ? 
      [ 
        set gl-chains-indices ( lput index-into-chains-lib gl-chains-indices )
        ;; show ( word "who: " who ", fitness: " fitness-measure ", index: " 
        ;;   index-into-chains-lib ) 
      ] 
    ]
     
    let chains-index fr-get-fit-chains-index
    while [ chains-index != -1 ]
    [
      let this-chain ( item chains-index gl-chains-lib )
      let this-chain-sn ( item 0 [chain-sn] of ( item 0 this-chain ) )
      LOG-TO-FILE ( word "Chk Chain (S/N, index): Ch(" this-chain-sn "," chains-index ") " )
      f-check-one-chain-hrmode-off this-chain
      
      set chains-index fr-get-fit-chains-index
    ]
  ]
  ;; End else
  
  ;; Supressed. f-update-aggregates

  LOG-TO-FILE "Do-Chk: procedure completed"
  
  ;; End of to do-check-chains
end 

;;-----------------------------------------------------------------------------|
;; The observer pulls a random index.

to-report fr-get-random-chains-index
  ;; The observer executes this routine.
  
  let next-index -1
  if( not ( empty? gl-chains-indices ) )
  [
    ;; Move a random index to the front of the list of indices.
    set gl-chains-indices ( shuffle gl-chains-indices )
    ;; Select that index to report back.
    set next-index ( item 0 gl-chains-indices )
    ;; Delete that index from the list.
    set gl-chains-indices ( but-first gl-chains-indices )
  ]
  
  ;; Report a valid as-yet-unused index, or -1 for an empty list.
  report next-index
  ;; End of to fr-get-next-chains-index
end 

;;-----------------------------------------------------------------------------|
;; the observer checks a chain to see if it needs to be updated

to f-check-one-chain-hrmode-on [ chain-to-check ]
  ;; The observer executes this routine.
  
  ;; This is the heart of the model.
  ;;   - If the primed OAM is not ready to discharge - do nothing.
  ;;   - Else, discharge and
  ;;   --- If this is not the last OAM, prime the next OAM.
  ;;   --- Else, replicate this chain, mutate and prime the offspring.
  
  ;; Retrieve the primed OAM (Open Atwood's Machine) indices.
  let this-head ( item 0 chain-to-check )
  let age-of-this-chain ( item 0 [age-of-chain] of this-head )
  LOG-TO-FILE ( word "  Age of chain: " age-of-this-chain )

  let rh-hoam-index ( item 0 [primed-rh-hoam-index] of this-head )
  let lh-hoam-index ( item 0 [primed-lh-hoam-index] of this-head )
  LOG-TO-FILE ( word "  OAM " rh-hoam-index )
  
  ;; Access the rh-hoam
  let rh-hoam ( item rh-hoam-index chain-to-check )
  
  ;; Determine if sufficient time has passed to exhaust waste heat.
  let discharge-age ( item 0 [age-to-discharge] of rh-hoam )

  LOG-TO-FILE ( word "  Discharge age: " discharge-age )
  if ( age-of-this-chain >= discharge-age )
  [
    LOG-TO-FILE ( word "  OAM " rh-hoam-index " discharging" )
    ;; The rh-hoam has smacked down on the floor.
    ;; Access the other half of the oam, the lh-hoam.
    let lh-hoam ( item lh-hoam-index chain-to-check )
    
    ;; Exhaust waste heat.
    let nrg-exhausted ( item 0 [energy-to-discharge] of rh-hoam )
    let ttl-lg-nrg ( item rh-hoam-index gl-ttl-lg-nrg-per-tick ) 
    set ttl-lg-nrg 
      ( ttl-lg-nrg + nrg-exhausted )
    set gl-ttl-lg-nrg-per-tick 
      ( replace-item lh-hoam-index gl-ttl-lg-nrg-per-tick ttl-lg-nrg )
    LOG-TO-FILE ( word "    Nrg exhausted: " nrg-exhausted )
  
    ;; Transfer of hg-nrg per tick is handled in f-update-aggregates.
    
    ;; The energy does not have to actually be transferred, as the amount is
    ;;   determined by the structure of the OAM for each OAM.  I.e. it is a
    ;;   pre-determined amount, and can be calculated within the OAM when it
    ;;   is primed, based on the size of the masses.  All masses are raised
    ;;   by the same g-drop-distance when the OAM is primed.
    ;; But I log it here.  It's a virtual transfer.
    let nrg-xferred ( item 0 [energy-to-transfer] of rh-hoam )
    LOG-TO-FILE ( word "    Nrg transferred: " nrg-xferred )
    
    ;; Check if this OAM is the last of the chain.
    ifelse ( lh-hoam-index = ( g-length-of-chains - 1 ) )
    [
      ;; It is the last OAM. Exhaust the remaining energy, de-activate the OAM,
      ;;   de-activate the chain, and replicate with variation.
      
      ;; Exhaust transferred energy as waste heat.
      ;; Data is stored in the aggregate list using the lh-hoam-index.
      set ttl-lg-nrg ( item lh-hoam-index gl-ttl-lg-nrg-per-tick ) 
      set ttl-lg-nrg ( ttl-lg-nrg + nrg-xferred ) ;; xferred nrg here exhausted.
      set gl-ttl-lg-nrg-per-tick
        ( replace-item lh-hoam-index gl-ttl-lg-nrg-per-tick ttl-lg-nrg )
      LOG-TO-FILE ( word "    Nrg exhausted by tail: " nrg-xferred )
      
      ;; Deactivate this OAM. This is done simply by changing the access 
      ;;   indices in the head back to defaults.  It is unnecessary, however, since
      ;;   the chain is being deactivated, mutated, and re-primed with 
      ;;   the head primed.
      ask this-head 
      [ 
        set rh-hoam-index 0
        set lh-hoam-index 1
      ]
      
      ;; The chain has completed processing of all energy received by the head.
      ;; The next call will (a) if possible, cause this chain to replicate, and
      ;;   (b) alter a random mass somewhere other than in the tail, for each
      ;;   of the two offspring chains.
      LOG-TO-FILE ( word "  Rep: Replication of chain ensues." )
      f-replicate-this-chain chain-to-check
     ]
    ;; else
    [
     ;; Prime the next OAM.
      LOG-TO-FILE ( word "    Priming OAM " lh-hoam-index )
      f-prime-oam ( rh-hoam-index + 1 ) ( lh-hoam-index + 1 ) chain-to-check
    ]
  ]
  ;; Else, primed OAM is not ready to discharge, do nothing.

  ;; End of f-check-one-chain-hrmode-on [ chain-to-check ]
end 

;;-----------------------------------------------------------------------------|
;; The observer pulls the next most fit index.

to-report fr-get-fit-chains-index
  ;; The observer executes this routine.

  let next-index -1
  if( not ( empty? gl-chains-indices ) )
  [
    ;; Indices are in order of descending fitness of chains.
    ;; Select the most fit index to report back.
    set next-index ( item 0 gl-chains-indices )
    ;; Delete that index from the list.
    set gl-chains-indices ( but-first gl-chains-indices )
  ]

  ;; Report a valid as-yet-unused index, or -1 for an empty list.
  report next-index
  ;; End of fr-get-fit-chains-index
end 

;;-----------------------------------------------------------------------------|
;; the observer checks a chain to see if it needs to be updated

to f-check-one-chain-hrmode-off [ chain-to-check ]
  ;; The observer executes this routine.
  
  ;; This is the heart of the 'no horse race' mode of the model.
  ;; Each chain is replicated in order from most fit downwards.
  ;;   As each fit chain is replicated, the least fit is replaced from the 
  ;;   bottom up.
  
  ;; In this mode, it does not matter which OAM in the chain is primed.  The
  ;;   decision as to when a chain replicates is not a horse race.  The decision 
  ;;   about fitness is entirely determined by examination of the energetics
  ;;   of the chain.  In every tick, all chains either replicate or are
  ;;   replaced.  This is purely a breeding program and 'natural selection' does
  ;;   not happen here.
  
  ;; Log the relevant data.
  let this-head ( item 0 chain-to-check )
  let this-chain-index ( item 0 [index-into-chains-lib] of this-head )
  let sn-of-this-chain ( item 0 [chain-sn] of this-head )
  LOG-TO-FILE ( word "  Checking: Ch(" sn-of-this-chain "," this-chain-index ")" )
  let fm-of-this-chain ( item 0 [fitness-measure] of this-head )
  LOG-TO-FILE ( word "    Fitness: " ( precision fm-of-this-chain 6 ) )
  let Mj-of-this-chain ( item 0 [Mj-geo-this-chain] of this-head )
  let Mt-of-this-chain ( item 0 [Mt-geo-this-chain] of this-head )
  let Eu-of-this-chain ( item 0 [Eu-geo-this-chain] of this-head )
  let Dt-of-this-chain ( item 0 [chain-time-to-drop] of this-head )
  LOG-TO-FILE ( word "    Mj: " ( precision Mj-of-this-chain 6 ) )
  LOG-TO-FILE ( word "    Mt: " ( precision Mt-of-this-chain 6 ) )
  LOG-TO-FILE ( word "    Mu: " ( precision Eu-of-this-chain 6 ) )
  LOG-TO-FILE ( word "    Dt: " ( precision Dt-of-this-chain 6 ) )

  ;; Exhaust waste heat.  Exclude the tail data.
  ;; TODO: Note, in this mode the final energy passed to the tail is not
  ;;   included in the discharge statistic.
  let tail-excluded ( but-last chain-to-check )
  let nrg-exhausted 0
  let nrg-transferred 0
  foreach tail-excluded
  [
    ask ?
    [
      let rh-hoam-index ( item 0 [index-into-chain] of ? )
      let lh-hoam-index ( rh-hoam-index + 1 )

      set nrg-exhausted ( item 0 [energy-to-discharge] of ? )
      let ttl-lg-nrg ( item rh-hoam-index gl-ttl-lg-nrg-per-tick ) 
      set ttl-lg-nrg 
        ( ttl-lg-nrg + nrg-exhausted )
      set gl-ttl-lg-nrg-per-tick 
        ( replace-item lh-hoam-index gl-ttl-lg-nrg-per-tick ttl-lg-nrg )

      set nrg-transferred ( item 0 [energy-to-transfer] of ? )
      let ttl-hg-nrg ( item rh-hoam-index gl-ttl-hg-nrg-per-tick ) 
      set ttl-hg-nrg 
        ( ttl-hg-nrg + nrg-transferred )
      set gl-ttl-hg-nrg-per-tick 
        ( replace-item lh-hoam-index gl-ttl-hg-nrg-per-tick ttl-hg-nrg )
    ]
  ]
  LOG-TO-FILE ( word "    Nrg exhausted: " nrg-exhausted )
  LOG-TO-FILE ( word "    Nrg transferred: " nrg-transferred )
  LOG-TO-FILE ( word "  Rep: Replication of chain ensues." )

  f-replicate-this-chain chain-to-check

  ;; End of f-check-one-chain-hrmode-on [ chain-to-check ]
end 

;;-----------------------------------------------------------------------------|
;; the observer checks a chain to see if it needs to be updated

to f-replicate-this-chain [ chain-to-replicate ]
  ;; The observer executes this routine.

  ;; This is the soul of the model
  ;; The list 'chain-to-replicate' is located somewhere in the super-list 
  ;;   'gl-chains-lib'.  If there is room for another, simply replicate by 
  ;;   sprouting a new chain of turtles in gl-new-chain, copying the data into 
  ;;   that new set of turtles, and then moving the turtles into the 
  ;;   gl-chains-lib library of chains.
  ;;   If there is no room for another chain, then the worst chain that has
  ;;   not yet discharged is terminated, and the offspring replaces it.  In that
  ;;   case, no new turtles are sprouted.
  ;; The chains are competing for the scarce resource of 'place on the list'.
  ;; That sounds silly, but, the parameter 'g-no-of-chains-max' is effectively
  ;;   the carrying capacity of this system, and it is a hard limit.  Those
  ;;   that process most quickly will stay on the list.  Those that process
  ;;   the most slowly will be removed, and replaced.
  ;;
  ;; Time to process is determined by low efficiency.  The least efficient
  ;;   transform their energy to kinetic energy and drop quickly, and 
  ;;   exhaust it as waste heat.  So, won't the average efficiency drop?
  ;;   As  drops, the load (energy delivered to the tail) drops.
  ;; The tail is of fixed mass.  The ultimate load is fixed.  So, the winner
  ;;   is the chain that can deliver that fixed load the most quickly.
  
  ;; Unpack the parent chain's serial number.
  let sn-of-ma ( item 0 [chain-sn] of ( item 0 chain-to-replicate ) )
  ;; Unpack the parent chain's index number.
  let index-of-ma ( item 0 [index-into-chains-lib] of ( item 0 chain-to-replicate ) )
  let index-of-da1 index-of-ma  ;; Index of first daughter, replaces mother.
  let index-of-da2 -1           ;; Index of second daughter.
  
  ;; Duplicate the target chain, by sprouting a new one, or copying over an old.
  let daughter-chain []
  ifelse ( g-no-of-chains < g-no-of-chains-max )
  [
    ;; There is room in the library of chains for another chain, which means
    ;;   there is a need for the creation of a new set of turtles.
    f-build-initialized-chain
    ;; This populates gl-new-chain with turtles, somewhat unnecessarily 
    ;;   initializes each, and transfers the whole chain into the gl-chains-lib, 
    ;;   and then, adjusts efficiencies to match the scenario.  This is all for
    ;;   the new turtles.  This is wasted computing, but the waste only goes on
    ;;   until gl-chains-lib is full.  So I have not tried to make it more
    ;;   efficient in processing time.  It does not compute energetics, 
    ;;   as that is handled below.
    
    ;; Clear construction area.
    set gl-new-chain []
    
    ;; Establish a handling name for the daughter chain within the library.
    ;; No new turtles are created, they are just listed in this list.
    set daughter-chain ( item ( g-no-of-chains - 1 ) gl-chains-lib )
    set index-of-da2 ( g-no-of-chains - 1 )

    ;; Copy everything except colour and location into the daughter chain.
    ;; This over-writes all of the data established during initialization.
    f-copy-chain-to-chain chain-to-replicate daughter-chain
    
    ;; There are now two almost identical copies in the library.
    ;; Give each a unique serial number, used for CSV output and analysis.
    ;; Ensure this-chain is ready to go.
    let daughter1-head ( item 0 chain-to-replicate )
    ask daughter1-head
    [
      set age-of-chain 0
    ]
    
    ;; Ensure daughter-chain is ready to go.
    let daughter2-head ( item 0 daughter-chain )
    ask daughter2-head
    [
      set index-into-chains-lib ( g-no-of-chains - 1 )
      set age-of-chain 0
    ]
  ]
  ;; else
  [
    ;; There is no room.  Find worst chain and replace it.
    
    let head-to-replicate ( item 0 chain-to-replicate )
    ;; Daughter2 cannot replace this chain.  Daughter1 replaces it.
    let index-to-exclude 
      ( item 0 [index-into-chains-lib] of head-to-replicate )
    ;; Find a suitable other chain to replace.
    let index-of-worst-chain
      fr-get-index-of-worst-chain index-to-exclude 
    
    ;; Write a 'data per x-action' record, if appropriate.
    WRITE-DPX-D-RECORD index-of-worst-chain "Discard"

    ;; Target the worst chain for replacement.
    set daughter-chain ( item index-of-worst-chain gl-chains-lib ) 
    let sn-of-chain ( item 0 [chain-sn] of item 0 daughter-chain )
    LOG-TO-FILE ( word "    Replacing Ch(" sn-of-chain "," index-of-worst-chain 
      ") with daughter chain" )

    ;; Replace the worst.  Copy everything except colour and location.
    f-copy-chain-to-chain chain-to-replicate daughter-chain
    set index-of-da2 index-of-worst-chain
    
    ;; There are now two almost identical copies in the library.
    ;; Give each a unique serial number, used for CSV output and analysis.
    ;; Ensure this-chain is ready to go.
    let daughter1-head ( item 0 chain-to-replicate )
    ask daughter1-head
    [
      set age-of-chain 0
    ]
    
    ;; Ensure daughter-chain is ready to go.
    let daughter2-head ( item 0 daughter-chain )
    ask daughter2-head
    [
      set index-into-chains-lib index-of-worst-chain
      ;; Correct the faulty age.
      set age-of-chain 0
    ]
  ]
  ;; End else
  
  ;; At this point both chain-to-replicate and daughter-chain exist and
  ;;   are in the library and are located in the arena.  They are identical
  ;;   except for colour, location, and serial numbers.
  
  ;; Write a 'data per x-action' record, if appropriate.
  WRITE-DPX-D-RECORD index-of-ma "Fission"
  
  ;; Update the serial numbers.
  let daughter1-head ( item 0 chain-to-replicate )
  ask daughter1-head
  [
    set chain-sn g-next-chain-sn
    set g-next-chain-sn ( g-next-chain-sn + 1 )
    set mas-sn sn-of-ma
  ]
  let daughter2-head ( item 0 daughter-chain )
  ask daughter2-head
  [
    set chain-sn g-next-chain-sn
    set g-next-chain-sn ( g-next-chain-sn + 1 )
    set mas-sn sn-of-ma
  ]
    
  let d1-sn ( item 0 [chain-sn] of daughter1-head )
  let d2-sn ( item 0 [chain-sn] of daughter2-head )
  let d1-in ( item 0 [index-into-chains-lib] of daughter1-head )
  let d2-in ( item 0 [index-into-chains-lib] of daughter2-head )
  LOG-TO-FILE ( word "    D1 chain is Ch(" d1-sn "," d1-in ")" )
  LOG-TO-FILE ( word "    D2 chain is Ch(" d2-sn "," d2-in ")" )

  ;; Mutate each chain.
  f-mutate-this-chain chain-to-replicate
  WRITE-DPX-D-RECORD index-of-da1 "Birth"
  f-mutate-this-chain daughter-chain
  WRITE-DPX-D-RECORD index-of-da2 "Birth"
  ;; While mutating, the energetics were re-computed and the 
  ;;   first OAM primed.

  ;; End of f-replicate-this-chain [ chain-to-replicate ]
end 

;;-----------------------------------------------------------------------------|
;; Get the fitness measure of this chain.

to-report fr-get-fitness-measure-of-chain [ of-this-chain ]
  ;; The observer executes this routine.
  
  let this-head ( item 0 of-this-chain )
  let active-fitness-measure 1
  
  if( g-fitness-number = g-fitness-joint )
    [ set active-fitness-measure ( item 0 [Mj-geo-this-chain] of this-head ) ]
  if( g-fitness-number = g-fitness-time )
    [ set active-fitness-measure ( item 0 [Mt-geo-this-chain] of this-head ) ]
  if( g-fitness-number = g-fitness-energy )
    [ set active-fitness-measure ( item 0 [Eu-geo-this-chain] of this-head ) ]
  
  report active-fitness-measure
  
  ;; End of fr-get-fitness-measure-of-chain
end 

;;-----------------------------------------------------------------------------|
;; Get the fitness measure of this head.

to-report fr-get-fitness-measure-of-head [ this-head ]
  ;; The observer executes this routine.
  
  let active-fitness-measure 1
  
  if( g-fitness-number = g-fitness-joint )
    [ set active-fitness-measure ( item 0 [Mj-geo-this-chain] of this-head ) ]
  if( g-fitness-number = g-fitness-time )
    [ set active-fitness-measure ( item 0 [Mt-geo-this-chain] of this-head ) ]
  if( g-fitness-number = g-fitness-energy )
    [ set active-fitness-measure ( item 0 [Eu-geo-this-chain] of this-head ) ]
  
  report active-fitness-measure
  
  ;; End of fr-get-fitness-measure-of-head
end 

;;-----------------------------------------------------------------------------|
;; Get the index of the worst chain in the library.

to-report fr-get-index-of-worst-chain [ excluded-index ]
  ;; The observer executes this routine.
  
  ;; This routine is used to find the worst chain in the library of chains,
  ;;   for the purpose of replicating the discharging chain into it.  The
  ;;   discharging chain, of course, should not be copied over itself, and
  ;;   so, its index is excluded from the search.
    
  ;; First, create an agentset of heads that exclude the appropriate head.
  let heads-to-include ( heads with [ not ( index-into-chains-lib = excluded-index ) ]  )
  ;; Then, exclude those with lower fitness measure.
  ;; set heads-to-include ( heads-to-include with [ fitness-measure <= min-fitness ] )
    
  ;; There are three difference fitness criteria:
  ;; - Mj - A joint criteria that finds a compromise.
  ;; - Mt - Minimize time to drop;
  ;; - Eu - Maximize useful energy passed on to next OAM;
  let list-of-worst [ -1 ]
  ifelse ( g-fitness-number = g-fitness-joint )
  [
    ;; Joint fitness measure invoked.
    set list-of-worst 
    ( [index-into-chains-lib] of 
      ( heads-to-include with-min [Mj-geo-this-chain] ) )
  ]
  ;; else - not joint
  [
    ifelse ( g-fitness-number = g-fitness-time )
    [
      ;; Time fitness measure invoked.
      set list-of-worst 
      ( [index-into-chains-lib] of 
        ( heads-to-include with-min [Mt-geo-this-chain] ) )
    ]
    ;; else - not time
    [
      ;; Energy fitness measure invoked.
      set list-of-worst 
      ( [index-into-chains-lib] of 
        ( heads-to-include with-min [Eu-geo-this-chain] ) )
    ]
    ;; End else
  ]
  ;; End else
  
  ;; We now have a list of indices of chains, any of which would be suitable.
  ;; Randomly order the list.
  set list-of-worst ( shuffle list-of-worst )
  
  ;; Choose one.
  let index-of-worst 0
  ifelse( empty? list-of-worst ) 
  [ set index-of-worst excluded-index ]
  [ set index-of-worst ( item 0 list-of-worst ) ]  
    
  ;; There is one thing left to do.  Since the 'worst' will be over-written
  ;;   with a fresh newly mutated chain of age zero, it should be removed from
  ;;   the list of chains checked in this turn.  If this is not done, those
  ;;   newly minted chains that replace an already-been-checked chain will
  ;;   have a disadvantage, having one less tick to perform in the race.  This
  ;;   may cause fluctuations that amount to noise.
    
  ;; Check if this index is in the list of as-yet unchecked chains.
  if ( member? index-of-worst gl-chains-indices )
  [
    let position-to-exclude ( position index-of-worst gl-chains-indices )
    set gl-chains-indices ( remove-item position-to-exclude gl-chains-indices )
  ]
    
  report index-of-worst
  
  ;; End of fr-get-index-of-worst-chain
end 

;;-----------------------------------------------------------------------------|
;; Copy from one chain to the other, contents of one turtle at a time.

to f-copy-chain-to-chain [ from-chain to-chain ]
  ;; The observer executes this routine.
  
  ;; Both chains must exist prior to copy action.  This copies the important
  ;;   content that is specific to OamLab.
  ;; This is the primary routine for enabling a 'fission' of the chain when a 
  ;;   chain is allowed to reproduce.  
  
  let hoam-index 0
  while [ hoam-index < g-length-Of-chains ]
  [
    let from-hoam ( item hoam-index from-chain )
    let to-hoam   ( item hoam-index to-chain )
    
    ifelse ( hoam-index = 0 ) [ f-copy-head-to-head from-hoam to-hoam ]
    [
      ifelse ( hoam-index < ( g-length-of-chains - 1 ) ) 
        [ f-copy-body-to-body from-hoam to-hoam ]
        [ f-copy-tail-to-tail from-hoam to-hoam ]
    ]
    set hoam-index ( hoam-index + 1 )
  ]
  
  ;; End of f-copy-chain-to-chain [ from-chain to-chain ]
end 

;;-----------------------------------------------------------------------------|
;; Copy contents from one head to another.

to f-copy-head-to-head [ from-head to-head ]
  ;; The observer executes this routine.
  
  ;; Both heads must have different who numbers.
  let from-who ( item 0 [who] of from-head )
  let to-who   ( item 0 [who] of to-head )
  ASSERT ( from-who != to-who ) 
    ( word "Copy error: who " from-who " = " to-who ) from-who
  
  ;; I don't know of an easy way to do this.  It looks messy.
  
  ;; Associated with chain.
  ask to-head [ set mas-sn 
    ( item 0 [mas-sn] of from-head ) ]
  ask to-head [ set chain-sn 
    ( item 0 [chain-sn] of from-head ) ]
  ask to-head [ set index-into-chains-lib 
    ( item 0 [index-into-chains-lib] of from-head ) ]
  ask to-head [ set age-of-chain 
    ( item 0 [age-of-chain] of from-head ) ]
  ask to-head [ set Mj-pi-this-chain 
    ( item 0 [Mj-pi-this-chain] of from-head ) ]
  ask to-head [ set Mt-pi-this-chain 
    ( item 0 [Mt-pi-this-chain] of from-head ) ]
  ask to-head [ set Eu-pi-this-chain 
    ( item 0 [Eu-pi-this-chain] of from-head ) ]
  ask to-head [ set Mj-geo-this-chain 
    ( item 0 [Mj-geo-this-chain] of from-head ) ]
  ask to-head [ set Mt-geo-this-chain 
    ( item 0 [Mt-geo-this-chain] of from-head ) ]
  ask to-head [ set Eu-geo-this-chain 
    ( item 0 [Eu-geo-this-chain] of from-head ) ]

  ask to-head [ set primed-rh-hoam-index 
    ( item 0 [primed-rh-hoam-index] of from-head ) ]
  ask to-head [ set primed-lh-hoam-index 
    ( item 0 [primed-lh-hoam-index] of from-head ) ]
  ;; ask to-head [ set default-colour 
  ;;   ( item 0 [default-colour] of from-head ) ]

  ;; Associated with HOAM.
  ask to-head [ set index-into-chain 
    ( item 0 [index-into-chain] of from-head ) ]
  ask to-head [ set mass 
    ( item 0 [mass] of from-head ) ]

  ;; Associated with rh-hoam.
  ask to-head [ set oam-time-to-drop 
    ( item 0 [oam-time-to-drop] of from-head ) ]
  ask to-head [ set age-to-discharge 
    ( item 0 [age-to-discharge] of from-head ) ]
  ask to-head [ set energy-to-transfer 
    ( item 0 [energy-to-transfer] of from-head ) ]
  ask to-head [ set energy-to-discharge 
    ( item 0 [energy-to-discharge] of from-head ) ]
  ask to-head [ set Mt-in-oam 
    ( item 0 [Mt-in-oam] of from-head ) ]
  ask to-head [ set Eu-in-oam 
    ( item 0 [Eu-in-oam] of from-head ) ]
  ask to-head [ set Mj-in-oam 
    ( item 0 [Mj-in-oam] of from-head ) ]

  ;; End of f-copy-head-to-head
end 

;;-----------------------------------------------------------------------------|
;; Copy contents from one body to another.

to f-copy-body-to-body [ from-body to-body ]
  ;; The observer executes this routine.
  
  ;; Both bodys must have different who numbers.
  let from-who ( item 0 [who] of from-body )
  let to-who   ( item 0 [who] of to-body )
  ASSERT ( from-who != to-who ) 
    ( word "Copy error: who " from-who " = " to-who ) from-who
  
  ;; I don't know of an easy way to do this.  It looks messy.
  
  ;; Associated with chain.
  ;; Nil.

  ;; Associated with HOAM.
  ask to-body [ set index-into-chain 
    ( item 0 [index-into-chain] of from-body ) ]
  ask to-body [ set mass 
    ( item 0 [mass] of from-body ) ]

  ;; Associated with rh-hoam.
  ask to-body [ set oam-time-to-drop 
    ( item 0 [oam-time-to-drop] of from-body ) ]
  ask to-body [ set age-to-discharge 
    ( item 0 [age-to-discharge] of from-body ) ]
  ask to-body [ set energy-to-transfer 
    ( item 0 [energy-to-transfer] of from-body ) ]
  ask to-body [ set energy-to-discharge 
    ( item 0 [energy-to-discharge] of from-body ) ]
  ask to-body [ set Mt-in-oam 
    ( item 0 [Mt-in-oam] of from-body ) ]
  ask to-body [ set Eu-in-oam 
    ( item 0 [Eu-in-oam] of from-body ) ]
  ask to-body [ set Mj-in-oam 
    ( item 0 [Mj-in-oam] of from-body ) ]

  ;; End of f-copy-body-to-body
end 

;;-----------------------------------------------------------------------------|
;; Copy contents from one tail to another.

to f-copy-tail-to-tail [ from-tail to-tail ]
  ;; The observer executes this routine.
  
  ;; Both tails must have different who numbers.
  let from-who ( item 0 [who] of from-tail )
  let to-who   ( item 0 [who] of to-tail )
  ASSERT ( from-who != to-who ) 
    ( word "Copy error: who " from-who " = " to-who ) from-who
  
  ;; I don't know of an easy way to do this.  It looks messy.
  
  ;; Associated with chain.
  ;; Nil.
  
  ;; Associated with HOAM.
  ask to-tail [ set index-into-chain 
    ( item 0 [index-into-chain] of from-tail ) ]
  ask to-tail [ set mass 
    ( item 0 [mass] of from-tail ) ]

  ;; Associated with rh-hoam.
  ;; Nil.

  ;; End of f-copy-tail-to-tail
end 

;;-----------------------------------------------------------------------------|
;; Alter one of the masses, other than the mass in the tail.

to f-mutate-this-chain [ chain-to-mutate ]
  ;; The observer executes this routine.

  let this-head ( item 0 chain-to-mutate )
  ask this-head [ set age-of-chain 0 set default-colour ( one-of gl-colour-pallette ) ]
  let this-chain-index ( item 0 [index-into-chains-lib] of this-head )
  let this-chain-sn ( item 0 [chain-sn] of this-head )
  LOG-TO-FILE ( word "  Mutating Ch(" this-chain-sn "," this-chain-index ")" )
  
  ;; Decide how many, and which, HOAMs can have mass mutated.
  let argument g-length-of-chains
  if( gb-mutate-heads = false ) [ set argument ( argument - 1 ) ]
  if( gb-mutate-tails = false ) [ set argument ( argument - 1 ) ]
  
  ;; Select an RH-HOAM randomly.
  let random-hoam-index random argument ;;  { 0, ..., (argument - 1 ) }
  ;; By default this includes the head.  Adjust upwards if needed.
  if( gb-mutate-heads = false ) [ set random-hoam-index ( random-hoam-index + 1 ) ]
  
  ;; Access the randomly selected HOAM.
  let this-hoam ( item random-hoam-index chain-to-mutate )
  LOG-TO-FILE ( word "    Mutating HOAM " random-hoam-index )
  
  ;; Extract the masses.
  let this-mass ( item 0 [mass] of this-hoam )
  let this-mass-was this-mass
  LOG-TO-FILE ( word "    Old mass: " this-mass )
  
  ;; Decide whether the mass in this HOAM will go up or down.
  let b-mass-goes-up random 2  ;; { 0, 1 }
  ;; Set a default size-factor
  let size-factor 1.0
  
  ;; When you adjust the mass in an HOAM you affect the efficiency of both
  ;;   OAMs formed using this HOAM.  An altered mass can make the combined
  ;;   time to discharge for both OAMs longer or shorter.  I want to make
  ;;   the change small enough that variances in time to process are not
  ;;   volatile, but large enough that the system can converge on a solution
  ;;   relatively quickly.  I have decided to use a random delta that is,
  ;;   at most, 1/4 of the distance to the previous or next mass
  
  ;; Compute a new mass for this HOAM.
  ;; Treat the head and tail differently from the others.
  ;; This is complicated, having six optional paths, all handled by ifelse.
  ifelse ( random-hoam-index = 0 )
  [
    ;; This-hoam is the head.
    ;; There is no prev-hoam.
    let next-hoam ( item ( random-hoam-index + 1 ) chain-to-mutate )
    let next-mass ( item 0 [mass] of next-hoam )

    ifelse ( b-mass-goes-up = 1 )
    [
      ;; Mass goes up.  It may go up by as much as 1/4 the distance
      ;;   to the next mass down.  Since, for the head, there is no next mass
      ;;   up, I use the next mass down to scale the change, but raise the 
      ;;   mass up.
      let mass-diff ( this-mass - next-mass )
      set size-factor ( ( random-float 1 ) / 4 )   ;; [0, 0.25 )
      set this-mass ( this-mass + ( size-factor * mass-diff ) )
    ]
    ;; else
    [
      ;; Mass goes down.  It may go down by as much as 1/4 the distance
      ;;   to the next mass.
      let mass-diff ( this-mass - next-mass )
      set size-factor ( ( random-float 1 ) / 4 )   ;; [0, 0.25 )
      let mass-delta ( -1 * size-factor * mass-diff )
      set this-mass ( this-mass + mass-delta )
    ]
  ] ;; End if ( random-hoam-index = 0 )
  ;; else
  [
    ;; This-hoam is not the head.  But it may be the tail, which also needs 
    ;;   special processing.
    
    ifelse ( random-hoam-index = ( g-length-of-chains - 1 ) )
    [
      ;; This-hoam is a tail HOAM.  There is no next HOAM.
      ;; Unpack the mass of the previous HOAM.
      let prev-hoam ( item ( random-hoam-index - 1 ) chain-to-mutate )
      let prev-mass ( item 0 [mass] of prev-hoam )
      
      ifelse ( b-mass-goes-up = 1 )
      [
        ;; Mass goes up.  It may go up by as much as 1/4 the distance
        ;;   to the previous mass.
        let mass-diff ( prev-mass - this-mass )
        set size-factor ( ( random-float 1 ) / 4 )  ;; [0, 0.25 ) 
        set this-mass ( this-mass + ( size-factor * mass-diff ) )
      ]
      ;; else
      [
        ;; Mass goes down.  It may go down by as much as 1/4 the distance
        ;;   to the next mass.
        let mass-diff this-mass ;; Special case for tail.
        set size-factor ( ( random-float 1 ) / 4 )   ;; [0, 0.25 ) 
        set this-mass ( this-mass - ( size-factor * mass-diff ) )
      ]
      ;; End else
    ]
    ;; Else
    [
      ;; This-hoam is a body HOAM.
      ;; Unpack the mass of the previous HOAM.
      let prev-hoam ( item ( random-hoam-index - 1 ) chain-to-mutate )
      let prev-mass ( item 0 [mass] of prev-hoam )
      ;; Unpack the mass of the next HOAM.
      let next-hoam ( item ( random-hoam-index + 1 ) chain-to-mutate )
      let next-mass ( item 0 [mass] of next-hoam )
      
      ifelse ( b-mass-goes-up = 1 )
      [
        ;; Mass goes up.  It may go up by as much as 1/4 the distance
        ;;   to the previous mass.
        let mass-diff ( prev-mass - this-mass )
        set size-factor ( ( random-float 1 ) / 4 )  ;; [0, 0.25 ) 
        set this-mass ( this-mass + ( size-factor * mass-diff ) )
      ]
      ;; else
      [
        ;; Mass goes down.  It may go down by as much as 1/4 the distance
        ;;   to the next mass.
        let mass-diff ( this-mass - next-mass )
        set size-factor ( ( random-float 1 ) / 4 )   ;; [0, 0.25 ) 
        set this-mass ( this-mass - ( size-factor * mass-diff ) )
      ]
      ;; End else
    ]
    ;; End else
  ]  ;; End else ( random-hoam-index != 0 )

  ;; Change mass in this-hoam, which is still in chain-to-mutate.
  ask this-hoam [ set mass this-mass ]
  LOG-TO-FILE ( word "    New mass: " this-mass )
  
  ;; And, finally, recompute the energetics of this mutated chain.
  f-compute-energetics-of-chain chain-to-mutate
  ;; And, prime the first OAM in the chain.
  ;; Each possible OAM in the chain was actually primed in the above
  ;;   call, from a programming point of view, but metaphorically, it
  ;;   is not primed until the previous OAM has discharged its energy.
  f-prime-oam 0 1 chain-to-mutate
 
  if( gb-dpx-on = 1 )
  [
    ;; Collect 'data per x-action' items if appropriate.
    let dpx-record-B ( n-values 5 [0.0] )  ;; Zeros
    
    let sn-of-ma ( item 0 [mas-sn] of this-head )
    set dpx-record-B ( replace-item 0 dpx-record-B sn-of-ma )

    let sn-of-chain ( item 0 [chain-sn] of this-head )
    set dpx-record-B ( replace-item 1 dpx-record-B sn-of-chain )

    set dpx-record-B ( replace-item 2 dpx-record-B random-hoam-index )
    set dpx-record-B ( replace-item 3 dpx-record-B this-mass-was )
    set dpx-record-B ( replace-item 4 dpx-record-B this-mass )

    WRITE-DPX-RECORD-B dpx-record-B
  ]
  
  ;; End of f-mutate-this-chain [ chain-to-mutate ]
end 
 
;;-----------------------------------------------------------------------------|
;; D3 - f-post-tick procedure(s)
;;-----------------------------------------------------------------------------|

to do-post-tick
  ;; This routine is to be executed by the observer.
   
  if( gb-debug-on = 1 )
  [
    ifelse( ( gs-debug-step-chooser = "all" ) or ( gs-debug-step-chooser = "post-tick" ) )
    [ set gb-debug-flow-on 1  LOG-TO-FILE "" LOG-TO-FILE word "Do-Post-tick: Debug on; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; MANUAL CHANGE FOR DEBUG.
  ;; This is a call to a debug routine which could be suppressed if all is okay.
  ;; This is one of a group of such calls, most of which are between steps in 
  ;;   the 'Go' routine.  They are suppressed there, but can be enabled again.
  ;; I have decided to leave this one active, for now.
  ;; It checks all agents, every tick, to ensure that all values are greater than
  ;;   or equal to zero.  
  if( frb-agents-are-all-valid = false ) [ LOG-TO-FILE ( word "Agents failed validity test." ) ]
  
  ;; Write "Data Per Tick" (dpt) macro data to CSV file, if it is turned on.
  DPT-DUMP
  
  ;; Update the aggregates for display in the monitors.
  f-update-aggregates

  display

  LOG-TO-FILE "Do-Pos: procedure completed."
  
  ;; End of to do-post-tick
end 

;;-----------------------------------------------------------------------------|
;; SECTION E – DRAWING AND MAINTENANCE PROCEDURE(S)
;;-----------------------------------------------------------------------------|

;;-----------------------------------------------------------------------------|
;; Update the values of global aggregate numbers.

to-report fr-geometric-mean [list-of-geo-means]
  ;; This routine is to be executed by the observer.
  ;;   As input it takes a list of numbers between 0 and 1 and produces
  ;;   the geometric mean of those numbers.  The list can be a list of
  ;;   geometric means of indices, or just a list of indices.
  
  let index 0
  let results 1  ;; Must be one.
  let this-number 0
  let list-length ( length list-of-geo-means )
  while [ index < list-length ]
  [
    set this-number ( item index list-of-geo-means )
    set results ( results * this-number )
    
    set index ( index + 1 )
  ]
  set results ( results ^ ( 1 / list-length ) )
  report results
  
  ;; End of fr-geometric-mean
end 

;;-----------------------------------------------------------------------------|
;; Update the values of global aggregate numbers.

to f-update-aggregates
  ;; This routine is to be executed by the observer.

  ;; Although this is a display-only routine, it implicitly calls the PRNG and
  ;;   so does have an effect on the trajectory of the model.  In a standard 'go'
  ;;   run it is called only once per tick, before graphs are updated.  If you
  ;;   use the one-step debug buttons, it is called once after each step, so
  ;;   debug runs that use those buttons will not replicate a real run.
  
  ;; Most per-tick aggregates are handled as they happen.  High-grade
  ;;   energy happens as the light mass rises, and it is computed here.
  
  ;; Zero all aggregates not part of per-tick actions.
  set gl-ttl-lg-nrg-per-hoam  ( n-values g-length-of-chains [0.0] )
  set gl-ttl-mass-per-hoam    ( n-values g-length-of-chains [0.0] )
  set gl-ttl-hg-nrg-per-oam   ( n-values ( g-length-of-chains - 1 ) [0.0] )
  set gl-pi-Mj-per-oam        ( n-values ( g-length-of-chains - 1 ) [1.0] )
  set gl-pi-Mt-per-oam        ( n-values ( g-length-of-chains - 1 ) [1.0] )
  set gl-pi-Eu-per-oam        ( n-values ( g-length-of-chains - 1 ) [1.0] )
  set gl-geo-Mj-per-oam       ( n-values ( g-length-of-chains - 1 ) [1.0] )
  set gl-geo-Mt-per-oam       ( n-values ( g-length-of-chains - 1 ) [1.0] )
  set gl-geo-Eu-per-oam       ( n-values ( g-length-of-chains - 1 ) [1.0] )

  set gl-ttl-hg-nrg-per-tick  ( n-values g-length-of-chains [0.0] )
  ;; set gl-ttl-lg-nrg-per-tick  ( n-values g-length-of-chains [0.0] )

  ;; All of these are collected as potential numerators of fractions.
  set g-no-of-hoams count turtles
  set g-no-of-heads count heads
  set g-no-of-bodies count bodies
  set g-no-of-tails count tails
  set g-ttl-age-of-chains sum [age-of-chain] of heads
  set g-ttl-dt-of-chains sum [chain-time-to-drop] of heads
  
  ;; These are the geometric mean of a set of geometric means.
  set g-geo-Mj ( fr-geometric-mean ( [Mj-geo-this-chain] of heads ) )
  set g-geo-Mt ( fr-geometric-mean ( [Mt-geo-this-chain] of heads ) )
  set g-geo-Eu ( fr-geometric-mean ( [Eu-geo-this-chain] of heads ) )
  
  ;; Declaration of needed variables.
  let this-chain-index 0
  let this-hoam-index 0
  let this-chain gl-new-chain ;; a dummy assignment
  let this-hoam one-of heads
  let value-from-hoam 0
  let value-from-list 0
  let time-for-this-drop 0
  
  ;; I have to do some tricky stuff here with indices into the lists
  ;;   because there are four rh-hoams in which data is collected that
  ;;   is associated with five transaction types:
  ;; - For hg energy, the energy coming into the first rh-hoam is not recorded.
  ;; - For hg energy, per tick, it must be computed, with the same problem.
  ;; - For lg energy, it's the tail exhausts all.
  ;; - For efficiency, there are four oams and four records.  A fifth is invented.
  
  ;; Loop through all hoams in all chains.
  while [ this-chain-index < g-no-of-chains ]
  [
    set this-chain ( item this-chain-index gl-chains-lib )
    
    set this-hoam-index 0
    while [ this-hoam-index < g-length-of-chains ]
    [
      set this-hoam ( item this-hoam-index this-chain )
      
      ;; Mass is the easiest to compile.
      set value-from-hoam item 0 ( [mass] of this-hoam ) 
      set value-from-list ( item this-hoam-index gl-ttl-mass-per-hoam )
      set value-from-list ( value-from-list + value-from-hoam )
      ;; Store it in the list
      set gl-ttl-mass-per-hoam
        ( replace-item this-hoam-index gl-ttl-mass-per-hoam value-from-list )
      
      ;; Some data is only associated with RH-HOAMS.
      if ( this-hoam-index < ( g-length-of-chains - 1 ) ) ;; I.e. not a tail
      [
        ;; High-grade energy
        ;; Calculate the amount transferred out of this rh-HOAM.
        set value-from-hoam ( item 0 [energy-to-transfer] of this-hoam ) 
        set value-from-list ( item this-hoam-index gl-ttl-hg-nrg-per-oam )
        set value-from-list ( value-from-list + value-from-hoam )
        ;; Store it in the list
        set gl-ttl-hg-nrg-per-oam
          ( replace-item this-hoam-index gl-ttl-hg-nrg-per-oam value-from-list )
          
        ;; Now, handle the per tick flow of hg nrg to the lh-hoam.
        set time-for-this-drop ( item 0 ( [oam-time-to-drop] of this-hoam ) )
        ifelse ( time-for-this-drop = 0 )
        [ set value-from-hoam 0 ]
        [ set value-from-hoam item 0 ( [energy-to-transfer] of this-hoam )
          set value-from-hoam ( value-from-hoam / time-for-this-drop ) ]
        set value-from-list ( item this-hoam-index gl-ttl-hg-nrg-per-tick )
        set value-from-list ( value-from-list + value-from-hoam )
        ;; Store it in the list
        set gl-ttl-hg-nrg-per-tick
          ( replace-item this-hoam-index gl-ttl-hg-nrg-per-tick value-from-list )

        ;; Now, handle total lg nrg.
        set value-from-hoam item 0 ( [energy-to-discharge] of this-hoam )
        set value-from-list ( item this-hoam-index gl-ttl-lg-nrg-per-hoam )
        set value-from-list ( value-from-list + value-from-hoam )
        ;; Store it in the list
        set gl-ttl-lg-nrg-per-hoam
          ( replace-item this-hoam-index gl-ttl-lg-nrg-per-hoam value-from-list )
      
        ;; The tail OAM needs to be handled as a special case of the HOAM that
        ;;   immediately precedes it.
        if ( this-hoam-index = ( g-length-of-chains - 2 ) )
        [
          ;; All of the energy transferred to the tail is exhausted.
          ;; Get 'transferred', but store as low grade or 'exhausted'.
          set value-from-hoam item 0 ( [energy-to-transfer] of this-hoam )
          set value-from-list ( item ( this-hoam-index + 1 ) gl-ttl-lg-nrg-per-hoam )
          set value-from-list ( value-from-list + value-from-hoam )
          ;; Store it in the list
          set gl-ttl-lg-nrg-per-hoam
            ( replace-item ( this-hoam-index + 1 ) gl-ttl-lg-nrg-per-hoam value-from-list )
        ]

        ;; And Mj.
        set value-from-hoam ( item 0 [Mj-in-oam] of this-hoam )
        set value-from-list ( item this-hoam-index gl-pi-Mj-per-oam )
        set value-from-list ( value-from-list * value-from-hoam )
        ;; Store it in the list
        set gl-pi-Mj-per-oam
          ( replace-item this-hoam-index gl-pi-Mj-per-oam value-from-list )

        ;; Mt.
        set value-from-hoam ( item 0 [Mt-in-oam] of this-hoam )
        set value-from-list ( item this-hoam-index gl-pi-Mt-per-oam )
        set value-from-list ( value-from-list * value-from-hoam )
        ;; Store it in the list
        set gl-pi-Mt-per-oam
          ( replace-item this-hoam-index gl-pi-Mt-per-oam value-from-list )

        ;; And Eu.
        set value-from-hoam ( item 0 [Eu-in-oam] of this-hoam )
        set value-from-list ( item this-hoam-index gl-pi-Eu-per-oam )
        set value-from-list ( value-from-list * value-from-hoam )
        ;; Store it in the list
        set gl-pi-Eu-per-oam
          ( replace-item this-hoam-index gl-pi-Eu-per-oam value-from-list )
      ]

      set this-hoam-index ( this-hoam-index + 1 )
    ]  ;; End of while [ this-hoam-index < g-length-of-chains ]

    set this-chain-index ( this-chain-index + 1 )
  ]  ;; Enf of while [ this-chain-index < g-no-of-chains ]
  
  ;; Compute the geometric averages using the products.
  set this-hoam-index 0
  let geometric-mean 0
  while [ this-hoam-index < ( g-length-of-chains - 1 ) ]
  [
     set value-from-list ( item this-hoam-index gl-pi-Mj-per-oam ) 
     set geometric-mean ( value-from-list ^ ( 1 / g-no-of-chains ) )
     set gl-geo-Mj-per-oam ( replace-item this-hoam-index gl-geo-Mj-per-Oam geometric-mean )
     
     set value-from-list ( item this-hoam-index gl-pi-Mt-per-oam ) 
     set geometric-mean ( value-from-list ^ ( 1 / g-no-of-chains ) )
     set gl-geo-Mt-per-oam ( replace-item this-hoam-index gl-geo-Mt-per-Oam geometric-mean )
     
     set value-from-list ( item this-hoam-index gl-pi-Eu-per-oam ) 
     set geometric-mean ( value-from-list ^ ( 1 / g-no-of-chains ) )
     set gl-geo-Eu-per-oam ( replace-item this-hoam-index gl-geo-Eu-per-Oam geometric-mean )
     
     set this-hoam-index ( this-hoam-index + 1 ) 
  ]
 
  ;;-----------------------------------------------------------------------------|
  ;; To ensure that the PRNG is called whether or not plots are displayed, the
  ;;   calculations needed for the histogram plots are carried out here where
  ;;   they will happen every tick.

  ;; This log entry may come from any step during debug operations.  
  LOG-TO-FILE "Do-xxx: All aggregates updated."  
  
  ;; End of f-update-aggregates
end 

;;--------------------------
;; DATA CAPTURE TO CSV FILES
;;--------------------------
  
;;-----------------------------------------------------------------------------|
;; Open a dpx file.

to f-open-dpx-file
  ;; This routine is to be executed by the observer.
  
  ;; DPX stands for 'Data Per Xaction'
  ;; Ensure previous dpx file is closed.
  f-close-dpx-file
  
  set gb-dpx-on 1
  set gs-dpx-status "1 (On)"
  set gs-dpx-file-name ( fr-construct-file-name "dpx" )
  set g-dpx-recno 0
  
  file-open gs-dpx-file-name
  
  ;; Write the mast head for the file.
  file-show "Data Per Transaction (DPX) File for a OamLab (NetLogo) Model."
  file-show word "File Name: " gs-dpx-file-name
  file-show ( word "Application Version Number: "gs-Version )
  file-show ""
    
  ifelse ( file-exists? gs-dpx-file-name )
  [
    ;; Send a message directly to the command centre.
    show word gs-dpx-file-name " opened."

    ;; Write the system parameter settings to the file.
    f-write-system-settings
    
    f-write-dpx-headers
  ]
  ;; else
  [
    ;; Send a message directly to the command centre.
    show word gs-dpx-file-name " not opened."
  
    set gb-dpx-on 0
    set gs-dpx-status "0 (Off)"
    set gs-dpx-file-name "DpxDummyName"
  ]
  
  ;; End of f-open-dpx-file
end 

;;-----------------------------------------------------------------------------|
;; Write header recordS to the dpx data file.

to f-write-dpx-headers
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpx-file-name
  
  ;; Write a header record for mutation data. 
  let line-out "DPX-A, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )

  set line-out ( word line-out "Ma's Serial #, " )
  set line-out ( word line-out "Serial #, " )
  set line-out ( word line-out "HOAM #, " )
  set line-out ( word line-out "Mass Was, " )
  set line-out ( word line-out "Mass Is now, " )

  file-print line-out
 
  ;; Write a header record for a mutated chain. 
  set line-out "DPX-C, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )

  ;; Head of chain
  set line-out ( word line-out "X-Action, " )
  set line-out ( word line-out "Ch: Ma's Serial #, " )
  set line-out ( word line-out "Ch: Serial #, " )
  set line-out ( word line-out "Ch: time-to-drop, " )
  set line-out ( word line-out "Ch: Mj, " )
  set line-out ( word line-out "Ch: Mt, " )
  set line-out ( word line-out "Ch: Eu, " )
  set line-out ( word line-out "He: Who #, " )
  set line-out ( word line-out "He: HOAM #, " )
  set line-out ( word line-out "He: HOAM-mass, " )
  set line-out ( word line-out "He: OAM-time-to-drop, " )
  set line-out ( word line-out "He: OAM-energy-to-transfer, " )
  set line-out ( word line-out "He: OAM-energy-to-discharge, " )
  set line-out ( word line-out "He: OAM-Mj, " )
  set line-out ( word line-out "He: OAM-Mt, " )
  set line-out ( word line-out "He: OAM-Eu, " )

  ;; Bodies within chain.
  let hoam-index 1
  while [ hoam-index < ( g-length-of-chains - 1 ) ] ;; Exclude head and tail.
  [
    set line-out ( word line-out "Bo: Who #, " )
    set line-out ( word line-out "Bo: HOAM #, " )
    set line-out ( word line-out "Bo: HOAM-mass, " )
    set line-out ( word line-out "Bo: OAM-time-to-drop, " )
    set line-out ( word line-out "Bo: OAM-energy-to-transfer, " )
    set line-out ( word line-out "Bo: OAM-energy-to-discharge, " )
    set line-out ( word line-out "Bo: OAM-Mj, " )
    set line-out ( word line-out "Bo: OAM-Mt, " )
    set line-out ( word line-out "Bo: OAM-Eu, " )
    
    set hoam-index ( hoam-index + 1 )
  ]

  set line-out ( word line-out "Ta: Who #, " )
  set line-out ( word line-out "Ta: HOAM #, " )
  set line-out ( word line-out "Ta: HOAM-mass " )

  file-print line-out
 
 ;; End of f-write-dpx-headers
end 

;;-----------------------------------------------------------------------------|
;; Write the data record type B (mutation event) for the dpx data file.

to WRITE-DPX-RECORD-B [ this-record ]
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpx-file-name
  
  ;; Write a data record for X-Action. 
  set g-dpx-recno ( g-dpx-recno + 1 )
  ;; Record type
  let line-out "DPX-B, "
  ;; Record number
  set line-out ( word line-out g-dpx-recno ", " )
  set line-out ( word line-out ticks ", " )

  set line-out ( word line-out ( item  0 this-record ) ", " ) ;; Ma's Serial #
  set line-out ( word line-out ( item  1 this-record ) ", " ) ;; Serial #
  set line-out ( word line-out ( item  2 this-record ) ", " ) ;; HOAM #
  set line-out ( word line-out ( item  3 this-record ) ", " ) ;; Mass was
  set line-out ( word line-out ( item  4 this-record ) ", " ) ;; Mass is now

  file-print line-out
  
  ;; End of WRITE-DPX-RECORD-B
end 

;;-----------------------------------------------------------------------------|
;; Write a record to the DPX file, if appropriate.

to WRITE-DPX-D-RECORD [ index-of-chain action ]
  ;; The observer executes this routine.
  
  ;; Only execute if "data per event" is toggled on.
  if ( gb-dpx-on = 1 )
  [
    ;; Select the file
    file-open gs-dpx-file-name
  
    ;; Increment the record number. 
    set g-dpx-recno ( g-dpx-recno + 1 )

    ;; Unpack the chain.
    let this-chain ( item index-of-chain gl-chains-lib ) 
    let this-value 0   ;; Dummy declaration
    
    ;; Record type
    let line-out "DPX-D, "
    set line-out ( word line-out g-dpx-recno ", " )
    set line-out ( word line-out ticks ", " )
    set line-out ( word line-out action ", " )

    ;; Unpack the head of chain
    let this-hoam ( item 0 this-chain )

    ;; Write data from the head.
    set this-value ( item 0 [mas-sn] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; Ma's serial number

    set this-value ( item 0 [chain-sn] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; Serial number

    set this-value ( item 0 [chain-time-to-drop] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; Chain-time-to-drop

    set this-value ( item 0 [Mj-geo-this-chain] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; Chain-Mj

    set this-value ( item 0 [Mt-geo-this-chain] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; Chain-Mt

    set this-value ( item 0 [Eu-geo-this-chain] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; Chain-Eu

    set this-value ( item 0 [who] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; Who #

    set this-value ( item 0 [index-into-chain] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; HOAM #

    set this-value ( item 0 [mass] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; HOAM-mass

    set this-value ( item 0 [oam-time-to-drop] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; OAM-time-to-drop

    set this-value ( item 0 [energy-to-transfer] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; OAM-energy-to-transfer

    set this-value ( item 0 [energy-to-discharge] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; OAM-energy-to-discharge

    set this-value ( item 0 [Mj-in-oam] of this-hoam )
    set line-out ( word line-out this-value ", "  ) ;; OAM-Mj

    set this-value ( item 0 [Mt-in-oam] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; OAM-Mt

    set this-value ( item 0 [Eu-in-oam] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; OAM-Eu

    ;; Bodies within chain.
    let hoam-index 1  ;; Exclude head, start at index = 1.
    while [ hoam-index < ( g-length-of-chains - 1 ) ] ;; Exclude tail.
    [
      set this-hoam ( item hoam-index this-chain )
      
      set this-value ( item 0 [who] of this-hoam )
      set line-out ( word line-out this-value ", " ) ;; Who#
      
      set this-value ( item 0 [index-into-chain] of this-hoam )
      set line-out ( word line-out this-value ", " ) ;; HOAM #
      
      set this-value ( item 0 [mass] of this-hoam )
      set line-out ( word line-out this-value ", " ) ;; HOAM-mass
      
      set this-value ( item 0 [oam-time-to-drop] of this-hoam )
      set line-out ( word line-out this-value ", " ) ;; OAM-time-to-drop
      
      set this-value ( item 0 [energy-to-transfer] of this-hoam )
      set line-out ( word line-out this-value ", " ) ;; OAM-energy-to-transfer
      
      set this-value ( item 0 [energy-to-discharge] of this-hoam )
      set line-out ( word line-out this-value ", " ) ;; OAM-energy-to-discharge
      
      set this-value ( item 0 [Mj-in-oam] of this-hoam )
      set line-out ( word line-out this-value ", " ) ;; OAM-Mj
      
      set this-value ( item 0 [Mt-in-oam] of this-hoam )
      set line-out ( word line-out this-value ", " ) ;; OAM-Mt
      
      set this-value ( item 0 [Eu-in-oam] of this-hoam )
      set line-out ( word line-out this-value ", " ) ;; OAM-Eu

      set hoam-index ( hoam-index + 1 )
    ]  ;; End while [ hoam-index < ( g-length-of-chains - 1 ) ]

    ;; The tail of the chain.
    set this-hoam ( item hoam-index this-chain )

    set this-value ( item 0 [who] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; Who #
      
    set this-value ( item 0 [index-into-chain] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; HOAM #
      
    set this-value ( item 0 [mass] of this-hoam )
    set line-out ( word line-out this-value ", " ) ;; HOAM-mass

    file-print line-out
  ]  ;; End if ( gb-dpx-on = 1 )
  
  ;; End of WRITE-DPX-D-RECORD
end 

;;-----------------------------------------------------------------------------|
;; Close the dpx file.

to f-close-dpx-file
  ;; This routine is to be executed by the observer.
  
  ;; DPX stands for 'Data Per Xaction'
  if ( Is-string? gs-dpx-file-name )
  [
    if ( file-exists? gs-dpx-file-name )
    [
      ;; Select the file
      file-open gs-dpx-file-name
      ;; Close it.
      file-close
    ]
  ]
  set gb-dpx-on 0
  set gs-dpx-status "0 (Off)"
  set gs-dpx-file-name "DpxDummyName"
  set g-dpx-recno 0
  
  ;; End of f-close-dpx-file
end 

;;-----------------------------------------------------------------------------|
;; Close and reopen the dpx file, it is too full.

to f-reopen-dpx-file
  ;; This routine is to be executed by the observer.
  
  f-close-dpx-file
  f-open-dpx-file

  ;; End of f-reopen-dpx-file
end 

;;-----------------------------------------------------------------------------|
;; Write a pair of records for the system settings.

to f-write-system-settings
  ;; This routine is to be executed by the observer.

  ;; A file must already be selected.
  ;; These system setting records are meant to be writtin right after the
  ;;   mast head lines.
  
  ;; Write a header record for system parameters.  
  let line-out "SYS-A, "
  set line-out ( word line-out "Version, " )
  set line-out ( word line-out "Scenario, " )
  set line-out ( word line-out "Fitness test, " )
  set line-out ( word line-out "PRNG-Seed, " )
  
  set line-out ( word line-out "g-no-of-chains-at-start, " )
  set line-out ( word line-out "g-no-of-chains-max, " )
  set line-out ( word line-out "g-length-of-chains, " )
  set line-out ( word line-out "g-drop-distance, " )
  set line-out ( word line-out "g-acceleration, " )
  set line-out ( word line-out "gb-mutate-heads, " )
  set line-out ( word line-out "gb-mutate-tails " )
  
  file-print line-out
  
  ;; Write a data record for system parameters.  
  set line-out "SYS-B, "
  set line-out ( word line-out gs-Version ", " )
  set line-out ( word line-out gs-scenario ", " )
  set line-out ( word line-out gs-fitness-measure ", " )
  set line-out ( word line-out g-use-this-seed ", " )
  
  set line-out ( word line-out g-no-of-chains-at-start ", " )
  set line-out ( word line-out g-no-of-chains-max ", " )
  set line-out ( word line-out g-length-of-chains ", " )
  set line-out ( word line-out g-drop-distance ", " )
  set line-out ( word line-out g-acceleration ", " )
  set line-out ( word line-out gb-mutate-heads ", " )
  set line-out ( word line-out gb-mutate-tails " " )
  
  file-print line-out
  
  ;; Now, write instructions on how to process the data.
  set line-out ( word "INSTRUCTIONS:" )
  file-print line-out
  set line-out ( word " - Copy the above rows of meta-data to a fresh sheet." )
  file-print line-out
  set line-out ( word " - Then delete the rows of meta-data and instructions." )
  file-print line-out
  set line-out ( word " - Then sort all columns and all rows of headers and data using Column A as sort key." )
  file-print line-out
  
  ;; End of f-write-system-settings
end 

;;-----------------------------------------------------------------------------|
;; Dump "Data Per Tick" data to dpt file, if open.

to DPT-DUMP
  ;; This routine is to be executed by the observer.

  ;; Activate only if the dpt file is open and ready to receive data.
  if( gb-dpt-on = 1 )
  [
    ;; If the file is full, close it.  MS Excel can handle 1,048,000 records.
    ;; Terminate the file before 1,000,000 records.
    ifelse( g-dpt-recno > g-recno-max ) [ f-reopen-dpt-file ]
    [
      ;; Activate once per tick.  Take a reading.
      ;; This collects macro-economic data of various kinds.
      f-write-dpt-macro-data 
    ]
  ]
  
  ;; End of DPT-DUMP
end 

;;-----------------------------------------------------------------------------|
;; Open a dpt file.

to f-open-dpt-file
  ;; This routine is to be executed by the observer.
  
  ;; DPT stands for 'Data Per Tick'
  ;; Ensure previous dpt file is closed.
  f-close-dpt-file
  
  set gb-dpt-on 1
  set gs-dpt-status "1 (On)"
  set gs-dpt-file-name ( fr-construct-file-name "dpt" )
  set g-dpt-recno 0
  
  file-open gs-dpt-file-name
 
  ;; Write the mast head for the file.
  file-show "Data Per Transaction (dpt) File for a OamLab (NetLogo) Model."
  file-show ( word "Application Version Number: "gs-Version )
  file-show word "File opened at:" date-and-time
  file-show ""
    
  ifelse ( file-exists? gs-dpt-file-name )
  [
    ;; Send a message directly to the command centre.
    show word gs-dpt-file-name " opened."

    ;; Write the system parameter settings to the file.
    f-write-system-settings
    
    ;; Write header records to the file.
    f-write-dpt-headers
  ]
  ;; else
  [
    ;; Send a message directly to the command centre.
    show word gs-dpt-file-name " not opened.  Writing dpt data cancelled."
  
    set gb-dpt-on 0
    set gs-dpt-status "0 (Off)"
    set gs-dpt-file-name "DptDummyName"
  ]
  
  ;; End of f-open-dpt-file
end 

;;-----------------------------------------------------------------------------|
;; Write the header records for the dpt data file.

to f-write-dpt-headers
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Write a header record for general macro-level data. 
  f-write-dpt-a-header
  
  ;; Write headers for data collected per HOAM.
  f-write-dpt-x-hoam-header "DPT-C" "Ave Mass per HOAM"
  f-write-dpt-x-hoam-header "DPT-E" "Ave Low-grade energy per HOAM"
  f-write-dpt-x-hoam-header "DPT-G" "Ave High-grade energy transferred"
  f-write-dpt-x-hoam-header "DPT-I" "Ave Low-grade energy exhausted"
  
  ;; Write headers for data collected per OAM.
  f-write-dpt-x-oam-header "DPT-K" "Ave High-grade energy per OAM"
  f-write-dpt-x-oam-header "DPT-M" "GeoAve Mj per OAM"
  f-write-dpt-x-oam-header "DPT-O" "GeoAve Mt per OAM"
  f-write-dpt-x-oam-header "DPT-Q" "GeoAve Eu per OAM"
  
  ;; Write header for data associated with switches that may be flipped.
  f-write-dpt-u-header
  
  ;; End of f-write-dpt-headers
end 

;;-----------------------------------------------------------------------------|
;; Write the header record, the DPT-A record type.

to f-write-dpt-a-header
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Write a header record for general macro-level data. 
  let line-out "DPT-A, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  
  set line-out ( word line-out "g-no-of-chains, " )
  set line-out ( word line-out "Ave drop time of chains, " )
  set line-out ( word line-out "Geo Ave Mj, " )
  set line-out ( word line-out "Geo Ave Mt, " )
  set line-out ( word line-out "Geo Ave Eu " )

  file-print line-out

  ;;End of f-write-dpt-a-header
end 
  
;;-----------------------------------------------------------------------------|
;; Write the header record, the DPT-X record type, per HOAM.

to f-write-dpt-x-hoam-header [ s-rectype s-recname ]
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Write a header record for averages by HOAM type. 
  let line-out ( word s-rectype ", " )
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  set line-out ( word line-out s-recname " " )
  
  let hoam-index 0
  while [  hoam-index < g-length-of-chains ]
  [
    set line-out ( word line-out ", HOAM " hoam-index " " )
        
    set hoam-index ( hoam-index + 1 )
  ]

  file-print line-out

  ;; End of f-write-dpt-x-hoam-header
end 
  
;;-----------------------------------------------------------------------------|
;; Write the header record, the DPT-X record type, per OAM.

to f-write-dpt-x-oam-header [ s-rectype s-recname ]
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Write a header record for averages by OAM type. 
  let line-out ( word s-rectype ", " )
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  set line-out ( word line-out s-recname " " )
  
  let oam-index 0
  while [ oam-index < ( g-length-of-chains - 1 ) ]
  [
    set line-out ( word line-out ", OAM " oam-index " " )
    set oam-index ( oam-index + 1 )
  ]

  file-print line-out

  ;; End of f-write-dpt-x-oam-header
end 
  
;;-----------------------------------------------------------------------------|
;; Write the header record, the DPT-U record type.

to f-write-dpt-u-header
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Write a header record for general macro-level data. 
  let line-out "DPT-U, "
  set line-out ( word line-out "RecNo, " )
  set line-out ( word line-out "Tick, " )
  ;; 
  set line-out ( word line-out "g-no-of-chains-max, " )
  set line-out ( word line-out "g-length-of-chains, " )
  set line-out ( word line-out "g-drop-distance, " )
  set line-out ( word line-out "g-acceleration, " )
  set line-out ( word line-out "gb-mutate-heads, " )
  set line-out ( word line-out "gb-mutate-tails " )
  file-print line-out
  
  ;; End of f-write-dpt-u-header
end 

;;-----------------------------------------------------------------------------|
;; Write the data records for the dpt data file.

to f-write-dpt-macro-data
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Write a data record for general macro-level data. 
  f-write-dpt-a-data
  
  ;; Write data collected per HOAM.
  f-write-dpt-x-hoam-data "DPT-D" "Ave Mass per HOAM" gl-ttl-mass-per-hoam
  f-write-dpt-x-hoam-data "DPT-F" "Ave Low-grade energy per HOAM" gl-ttl-lg-nrg-per-hoam
  f-write-dpt-x-hoam-data "DPT-H" "Ave Hg energy transferred" gl-ttl-hg-nrg-per-tick
  f-write-dpt-x-hoam-data "DPT-J" "Ave Lg energy exhausted" gl-ttl-lg-nrg-per-tick
  
  ;; Write data collected per OAM.
  f-write-dpt-x-oam-data "DPT-L" "Ave High-grade energy per OAM" gl-ttl-hg-nrg-per-oam
  f-write-dpt-x-oam-data "DPT-P" "Geo Ave Mt" gl-geo-Mt-per-oam
  f-write-dpt-x-oam-data "DPT-N" "Geo Ave Eu" gl-geo-Eu-per-oam 
  f-write-dpt-x-oam-data "DPT-T" "Geo Ave Mj" gl-geo-Mj-per-oam
  
  ;; Write data associated with switches that may be flipped.
  f-write-dpt-u-data
  
  ;; End of f-write-dpt-macro-data
end 

;;-----------------------------------------------------------------------------|
;; Write the data record, the dpt-a data record.

to f-write-dpt-a-data
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Increment the record number.
  set g-dpt-recno ( g-dpt-recno + 1 )

  ;; Write a data record for general macro-level data. 
  let line-out "DPT-B, "
  set line-out ( word line-out g-dpt-recno ", " )
  set line-out ( word line-out ticks ", " )
  
  let value-out 0

  set line-out ( word line-out g-no-of-chains ", " )

  set value-out ( g-ttl-dt-of-chains / g-no-of-chains )
  set line-out ( word line-out value-out ", " )

  set value-out g-geo-Mj
  set line-out ( word line-out value-out ", " )

  set value-out g-geo-Mt
  set line-out ( word line-out value-out ", " )

  set value-out g-geo-Eu
  set line-out ( word line-out value-out " " )

  file-print line-out
  
  ;; End of f-write-dpt-a-data
end 

;;-----------------------------------------------------------------------------|
;; Write the data record, the DPT-X record type, per HOAM.

to f-write-dpt-x-hoam-data [ s-rectype s-recname this-list ]
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Increment the record number.
  set g-dpt-recno ( g-dpt-recno + 1 )

  ;; Write a data record for averages per HOAM. 
  let line-out ( word s-rectype ", " )
  set line-out ( word line-out g-dpt-recno ", " )
  set line-out ( word line-out ticks ", " )
  
  set line-out ( word line-out s-recname " " )
  
  let value-out 0   ;; Dummy declaration
  let hoam-index 0
  while [  hoam-index < g-length-of-chains ]
  [
    set value-out ( item hoam-index this-list )
    set value-out ( value-out / g-no-of-chains )
    set line-out ( word line-out ", " value-out " " )
        
    set hoam-index ( hoam-index + 1 )
  ]

  file-print line-out

  ;; End of f-write-dpt-x-hoam-data
end 
  
;;-----------------------------------------------------------------------------|
;; Write the data record, the DPT-X record type, per OAM.

to f-write-dpt-x-oam-data [ s-rectype s-recname this-list ]
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Increment the record number.
  set g-dpt-recno ( g-dpt-recno + 1 )
  
  ;; Write a header record for averages by OAM type. 
  let line-out ( word s-rectype ", " )
  set line-out ( word line-out g-dpt-recno ", " )
  set line-out ( word line-out ticks ", " )
  
  set line-out ( word line-out s-recname " " )
  
  let value-out 0  ;; Dummy declaration.
  let oam-index 0
  while [ oam-index < ( g-length-of-chains - 1 ) ]
  [
    set value-out ( item oam-index this-list )
    set value-out ( value-out / g-no-of-chains )
    set line-out ( word line-out ", " value-out " " )
    
    set oam-index ( oam-index + 1 )
  ]

  file-print line-out

  ;; End of f-write-dpt-x-oam-data
end 
  
;;-----------------------------------------------------------------------------|
;; Write the data record, the DPT-V record type.

to f-write-dpt-u-data
  ;; This routine is to be executed by the observer.

  ;; Select the file
  file-open gs-dpt-file-name
  
  ;; Increment the record number.
  set g-dpt-recno ( g-dpt-recno + 1 )

  ;; Write a data record for quasi-variable switches. 
  let line-out "DPT-V, "
  set line-out ( word line-out g-dpt-recno ", " )
  set line-out ( word line-out ticks ", " )
  
  set line-out ( word line-out g-no-of-chains-max ", " )
  set line-out ( word line-out g-length-of-chains ", " )
  set line-out ( word line-out g-drop-distance ", " )
  set line-out ( word line-out g-acceleration ", " )
  set line-out ( word line-out gb-mutate-heads ", " )
  set line-out ( word line-out gb-mutate-tails " " )
  file-print line-out
  
  ;; End of f-write-dpt-u-data
end 

;;-----------------------------------------------------------------------------|
;; Close the dpt file.

to f-close-dpt-file
  ;; This routine is to be executed by the observer.
  
  ;; DPT stands for 'Data Per Tick'
  if ( Is-string? gs-dpt-file-name )
  [
    if ( file-exists? gs-dpt-file-name )
    [
      ;; Select the file
      file-open gs-dpt-file-name
      ;; Close it.
      file-close
    ]
  ]
  set gb-dpt-on 0
  set gs-dpt-status "0 (Off)"
  set gs-dpt-file-name "DptDummyName"
  set g-dpt-recno 0
  
  ;; End of f-close-dpt-file
end 

;;-----------------------------------------------------------------------------|
;; Close and reopen the dpt file, it is too full.

to f-reopen-dpt-file
  ;; This routine is to be executed by the observer.
  
  f-close-dpt-file
  f-open-dpt-file

  ;; End of f-reopen-dpt-file
end 

;;-----------------------------------------------------------------------------|
;; Construct a CSV data file name.

to-report fr-construct-file-name [ type-string ]
  ;; This routine is to be executed by the observer.
  ;;
  ;; Date-string format "01:19:36.685 PM 19-Sep-2002"
  let date-string date-and-time
  let file-name ( word "OamLab_" type-string "_" )
  ;; Append the year as yy.
  set file-name word file-name ( substring date-string 25 27 )
  ;; Append the month as Mmm.
  set file-name word file-name fr-convert-mmm-mm ( substring date-string 19 22 )
  ;; Append the day as dd.
  set file-name word file-name ( substring date-string 16 18 )
  ;; Append a dash.
  set file-name word file-name "_"

  ;; Append the hour as hh.
  set file-name word file-name fr-convert1224 ( substring date-string 0 2 ) ( substring date-string 13 15 )
  ;; Append the minute as mm.
  set file-name word file-name ( substring date-string 3 5 )
  ;; Append the second as ss.
  set file-name word file-name ( substring date-string 6 8 )
  ;; Append the .csv extension.
  set file-name word file-name ".csv"

  report file-name
  
  ;; End of fr-construct-file-name
end 



;;-----------------------------------------------------------------------------|
;; DEBUG AND DEBUG LOG FILE MANAGEMENT FUNCTIONS
;;-----------------------------------------------------------------------------|

;;-----------------------------------------------------------------------------|
;; Open a log file for debug output.

to f-open-log-file
  ;; This routine is to be executed by the observer.
  
  ;; Ensure previous log file is closed.
  if ( is-string? gs-log-file-name )
  [
    if ( file-exists? gs-log-file-name )
    [
      file-close-all
    ]
  ]
  
  ;; Date-string format "01:19:36.685 PM 19-Sep-2002"
  let date-string date-and-time
  set gs-log-file-name "OamLab_Log_"
  ;; Append the year as yy.
  set gs-log-file-name word gs-log-file-name ( substring date-string 25 27 )
  ;; Append the month as Mmm.
  set gs-log-file-name word gs-log-file-name fr-convert-mmm-mm ( substring date-string 19 22 )
  ;; Append the day as dd.
  set gs-log-file-name word gs-log-file-name ( substring date-string 16 18 )
  ;; Append a dash.
  set gs-log-file-name word gs-log-file-name "_"

  ;; Append the hour as hh.
  set gs-log-file-name word gs-log-file-name fr-convert1224 ( substring date-string 0 2 ) ( substring date-string 13 15 )
  ;; Append the minute as mm.
  set gs-log-file-name word gs-log-file-name ( substring date-string 3 5 )
  ;; Append the second as ss.
  set gs-log-file-name word gs-log-file-name ( substring date-string 6 8 )
  ;; Append the .txt extension.
  set gs-log-file-name word gs-log-file-name ".txt"

  file-open gs-log-file-name
  file-show "Log File for a OamLab (NetLogo) Model."
  file-show word "File Name: " gs-log-file-name
  file-show word "File opened at:" date-and-time
  file-show ""
  
  ;; Send a message directly to the command centre.
  ifelse ( file-exists? gs-log-file-name )
  [
    show word gs-log-file-name " opened."
  ]
  [
    show word gs-log-file-name " not opened."
  ]
  
  ;; End of f-open-log-file
end 

;;-----------------------------------------------------------------------------|
;; Convert month in text form to digital form.

to-report fr-convert-mmm-mm [ mmm ]
  ;; This routine is to be executed by the observer.
  ;; It converts a string in the form mmm ( alpha text ) to the form mm ( digit-text ).
  
  let mm "00"
  if( mmm = "Jan" ) [ set mm "01" ]
  if( mmm = "Feb" ) [ set mm "02" ]
  if( mmm = "Mar" ) [ set mm "03" ]
  if( mmm = "Apr" ) [ set mm "04" ]
  if( mmm = "May" ) [ set mm "05" ]
  if( mmm = "Jun" ) [ set mm "06" ]
  if( mmm = "Jul" ) [ set mm "07" ]
  if( mmm = "Aug" ) [ set mm "08" ]
  if( mmm = "SeP" ) [ set mm "09" ]
  if( mmm = "Oct" ) [ set mm "10" ]
  if( mmm = "Nov" ) [ set mm "11" ]
  if( mmm = "Dec" ) [ set mm "12" ]
  report mm
  
  ;; End of fr-convert-mmm-mm
end 

;;-----------------------------------------------------------------------------|
;; Convert hour in 12 format to 24 hour format.

to-report fr-convert1224 [ hh ampm ]
  ;; This routine is to be executed by the observer.
  ;; It converts a string in 12 hour format to 24 hour format.
  
  let hour read-from-string hh
  if( ampm = "PM" ) [ set hour ( hour + 12 ) ]
  
  let dd ( word "00" hour )
  let d2 last dd
  set dd but-last dd
  let d1 last dd
  set dd ( word d1 d2 )
  report dd
  
  ;; End of fr-convert1224
end 

;;-----------------------------------------------------------------------------|
;; Close a log file for debug output.

to f-close-log-file
  ;; This routine is to be executed by the observer.
  
  let b-filename-exists 0
  if ( is-string? gs-log-file-name ) 
  [
    if ( file-exists? gs-log-file-name )
    [
      set b-filename-exists 1
    ]
  ] 

  ifelse( b-filename-exists = 1 )
  [
    ;; Ensure the file is selected.
    file-open gs-log-file-name
      
    ;; Stanp it.
    LOG-TO-FILE word "File closed at: " date-and-time
      
    ;; Flush the buffers.
    file-flush 
      
    ;; Close it.
    file-close-all
      
    ;; Note sent to command centre.
    show word gs-log-file-name " closed."
    
    ;; Revert to dummy name.
    set gs-log-file-name "dummyname"
  ]
  [
    if( gs-log-file-name = "dummyname" )
      [ show "No log file is open.  Cannot close it." ]
  ]
  
  ;; End of f-close-log-file
end 

;;-----------------------------------------------------------------------------|
;; Select an already opened log file.

to f-select-log-file
  ;; This routine is to be executed by the observer.
  
  ifelse ( file-exists? gs-log-file-name )
  [
    ;; Ensure the file is selected.
    file-open gs-log-file-name
    
    ;; Ensure it is open for writing.
    LOG-TO-FILE ""
    LOG-TO-FILE "SELECTED"    
  ]
  [
    show word gs-log-file-name " is not open.  Cannot select it."
  ]
  
  ;; End of f-select-log-file
end 

;;-----------------------------------------------------------------------------|
;; Change the debug mode from on to off, or vice versa.

to f-toggle-debug
  ;; This routine is to be executed by the observer, and is activated by a 
  ;;   button.
  
  ifelse( gb-debug-on = 1 )
  [
    ;; Debug is On, turn it Off.
    ;; Close the file before turning debug logging off.
    f-close-log-file
    set gs-debug-status "0 (Off)"  ;; This appears in the monitor.
    set gb-debug-on 0              ;; But this controls the debug feature.
  ]
  [
    ;; Debug is Off, turn it On.
    set gs-debug-status "1 (On)"   ;; This appears in the monitor.
    set gb-debug-on 1              ;; But this controls the debug feature.
    ;; The switches, if needed, are reset manually by the user.
    ;; Open the log file after turning debug logging on.
    f-open-log-file
  ]
  
  ;; End of f-toggle-debug
end 

;;-----------------------------------------------------------------------------|
;; 'Show' a string in a debug log.

to LOG-TO-FILE [ log-this-string ]
  ;; This routine may be executed by observer or turtle.
  ;; It should be invoked as a debug routine only, and would not be used for 
  ;;    normal output.  It sends output to the debug log file, or, optionally,
  ;;    also to the command centre.
  
  ;; gb-debug-on is a global Boolean and has value 1 (true) or 0 (false).
  if( gb-debug-on = 1 )
  [
    ;; gb-debug-flow-on is declared as a global Boolean variable, and its value 
    ;;   is 0 ( false ) or 1 ( true ) and is set on or off at the beginning of each 
    ;;   function ( each do-step ).  It is controlled by the chooser that selects 'all' 
    ;;   or a specific do-function.
    ;; 
    ;; When it is 'on' you can assume the debug log file exists and is open for
    ;;   write.
    
    if( gb-debug-flow-on = 1 )
    [
      file-show log-this-string
      show log-this-string
    ] 
  ]
  
  ;; End of LOG-TO-FILE
end 

;;-----------------------------------------------------------------------------|
;; This replicates the effect of an 'ASSERTION' in C++

to ASSERT [ error-test error-string error-who ]
;; This routine can be run by any of observer or turtle (I think).

if( error-test = false )
[
  show ( word error-test " " error-string " " error-who )
  ;; Cause a run-time error and display a message.
  error ( word "Agent: " error-who " - " error-string )
]

  ;; End of ASSERT
end 


;;-----------------------------------------------------------------------------|
;; Check whether the agents are all valid.

to-report frb-agents-are-all-valid 
;; This routine can be run by the observer.

  let b-agents-are-all-valid true
  
  if( gb-debug-on = 1 )
  [
    ;; Do the check only if debug is on.
    
    ;; Check the heads.
    ask heads
    [
      if( frb-head-is-valid = false ) [ set b-agents-are-all-valid false ]
    ]
    
    ;; Check the bodies.
    ask bodies
    [
      if( frb-body-is-valid = false ) [ set b-agents-are-all-valid false ]
    ]
    
    ;; Check the tails.
    ask tails
    [
      if( frb-tail-is-valid = false ) [ set b-agents-are-all-valid false ]
    ]
  ]
  
  report b-agents-are-all-valid
  
  ;; End of frb-agents-are-all-valid
end 

;;-----------------------------------------------------------------------------|
;; Check whether a head is valid.

to-report frb-head-is-valid 
;; This routine can be run by a head.

  let b-head-is-valid true
  
  if( index-into-chains-lib < 0 ) 
  [ 
    set b-head-is-valid false 
    LOG-TO-FILE ( word "index-into-chains-lib = " index-into-chains-lib "; at tick = " ticks )
  ]
  
  report b-head-is-valid
  
  ;; End of frb-head-is-valid
end 

;;-----------------------------------------------------------------------------|
;; Check whether a body is valid.

to-report frb-body-is-valid 
;; This routine can be run by a body.

  let b-body-is-valid true

  if( mass < 0 ) 
  [ 
    set b-body-is-valid false 
    LOG-TO-FILE ( word "mass = " mass "; at tick = " ticks )
  ]
  
  report b-body-is-valid
  
  ;; End of frb-body-is-valid
end 

;;-----------------------------------------------------------------------------|
;; Check whether a tail is valid.

to-report frb-tail-is-valid 
;; This routine can be run by a tail.

  let b-tail-is-valid true
  if( mass < 0 ) 
  [ 
    set b-tail-is-valid false 
    LOG-TO-FILE ( word "mass = " mass "; at tick = " ticks )
  ]
 
  report b-tail-is-valid
  
  ;; End of frb-tail-is-valid
end 

;;-----------------------------------------------------------------------------|
;; DISPLAY MONITOR MECHANISMS
;;-----------------------------------------------------------------------------|

;;-----------------------------------------------------------------------------|
;; Reports the fitness measure of the system based on the current choice of
;;   fitness measures, i.e. the active fitness regime.

to-report fr-get-active-fitness-measure 
  ;; This routine is to be executed by the observer.

  let active-fitness-measure 1
  
  if( g-fitness-number = 0 ) [ set active-fitness-measure g-geo-Mj ]
  if( g-fitness-number = 1 ) [ set active-fitness-measure g-geo-Mt ]
  if( g-fitness-number = 2 ) [ set active-fitness-measure g-geo-Eu ]
  
  report active-fitness-measure
  
  ;; End of fr-get-active-fitness-measure
end 

;;-----------------------------------------------------------------------------|
;; SPECIAL SCENARIO
;;-----------------------------------------------------------------------------|

;; This is for a special scenario in which all tails are the same, all heads
;;   are the same, and there is mixed efficiency at start.  There is a button
;;   that invokes the g-set-all-heads-at-max, a monitor that displays 
;;   g-max-all-heads, and an input control that allows you to choose what
;;   value all heads will be set to.  You are expected to set the chooser to
;;   'energy' fitness measure and 'Mixed Odum Efficiency' yourself. 

;;-----------------------------------------------------------------------------|
;;  This routine is used by a monitor to report the maximum mass in all heads.

to-report fr-get-max-head-size 
  ;; This routine is to be executed by the observer.

  set g-max-head-size ( max [mass] of heads )
  report g-max-head-size
  
  ;; End of fr-get-max-head-size
end 

;;-----------------------------------------------------------------------------|
;;  This routine is used by a monitor to report the minimum mass in all tails.

to-report fr-get-min-tail-size 
  ;; This routine is to be executed by the observer.

  set g-min-tail-size ( min [mass] of tails )
    
  report g-min-tail-size
  ;; End of fr-get-min-tail-size
end 

;;-----------------------------------------------------------------------------|
;;  This routine is used by a button to increase the size of the mass of 
;;    all heads to the value in an input box.

to f-make-all-heads-the-same 
;; This routine can be run by the observer.

  ;; Note the current value.
  let max-head-size-is ( fr-get-max-head-size )
  
  ;; Check whether a higher value has been entered into the input box.
  ifelse( g-set-max-head-size > max-head-size-is )
  [
    ;; Effect the change.
    ask heads
    [
      set mass ( g-set-max-head-size )
    ]
    ;; Recalculate all drop times, efficiencies, and fitness measures.
    f-compute-energetics-of-chains
    ;; Update the aggregates again, after energetics computed.
    f-update-aggregates  ;; Totals and averages.
    clear-all-plots
    setup-plots
   
    ;; Return the input box to its default status.
    set g-set-max-head-size -1
  ]
  ;; else
  [
    ;; Case of invalid input.
    ;; Return the input box to its default status.
    set g-set-max-head-size -2
  ]
  ;; End else

  ;; End of f-make-all-heads-the-same
end 

;;-----------------------------------------------------------------------------|
;; PLOT MANAGEMENT MECHANISMS
;;-----------------------------------------------------------------------------|

  ;; nil
  

There is only one version of this model, created over 7 years ago by Garvin Boyle.

Attached files

File Type Description Last updated
02 OamLab V1.10.png preview Preview for '02 OamLab V1.10' over 7 years ago, by Garvin Boyle Download
141129 NTF - NetLogo Stds for OrrerySW R2.pdf pdf Prepared standards for Orrery Software for NetLogo projects. over 7 years ago, by Garvin Boyle Download
150101 NTF Atwood's Machine R4.pdf pdf An analysis of the functioning of Atwood's Machine. over 7 years ago, by Garvin Boyle Download
150105 NTF AM Shape Study R1.pdf pdf A study of the shape of the power vs efficiency curve of Atwood's Machine. over 7 years ago, by Garvin Boyle Download
150113 NTF Atwoods Machine Revisited R4.pdf pdf More thoughts on the operations of Atwood's Machine as a model for energy transfers. over 7 years ago, by Garvin Boyle Download
150418 NTF Three Shapes of AM Revisited R2.pdf pdf A more detailed study of the power vs efficiency curves associated with Atwood's Machine. over 7 years ago, by Garvin Boyle Download
170328 NTF OamLab Change Diary.pdf pdf The most recent change diary. over 7 years ago, by Garvin Boyle Download
170330 NTF High-Level Design - OAMLab R5.pdf pdf A high-level technical description of the model. over 7 years ago, by Garvin Boyle Download

This model does not have any ancestors.

This model does not have any descendants.