03 MppLab V1.09

03 MppLab V1.09 preview image

1 collaborator

121210_portrait_of_garvin Garvin Boyle (Author)

Tags

atwood's machine 

Tagged by Garvin Boyle 14 days ago

biophysical economics 

Tagged by Garvin Boyle 14 days ago

ecological economics 

Tagged by Garvin Boyle 14 days ago

maximum power principle 

Tagged by Garvin Boyle 14 days ago

sustainability 

Tagged by Garvin Boyle 14 days ago

sustainable economics 

Tagged by Garvin Boyle 14 days ago

Model group Sustainability | Visible to everyone | Changeable by group members (Sustainability)
Model was written in NetLogo 5.0.5 • Viewed 52 times • Downloaded 0 times • Run 0 times
Download the '03 MppLab V1.09' modelDownload this modelEmbed this model

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


## WHAT IS IT?

**MppLab** - This is the second of a series of three planned models in a study of the maximum power principle (MPP) - the other two models being **OamLab** and **TpLab**. In **MppLab** energy arrives in a steady stream from the Sun and is captured by plants that act as the primary producers in a trophic web. The artificially distinct trophic chains studied in **OamLab** now merge to form a complex evolving web of organisms from herbivores to apex carnivores. By this means we have deeper insight into the basic implications of Lotka's argument (Lotka, 1922a) and the arguments of Odum and Pinkerton (1955). While Lotka's focus was on system-wide processes consisting of many serial energy transformations, Odum's focus was on individual energy transformations. While Lotka argued that system-wide processes maximize the degradation of energy, Odum argued that the individual energy transformations within them each minimized the degradation of energy. Can both opinions be true? How do we reconcile such clearly antithetic views? Is it possible to model the evolution of a complete trophic web, from primary producers to apex predators, in which (a) organisms diverge into separate species; (b) individual energy transformations evolve to become ever more powerful in their preservation of energy; and (c) system-wide trophic web evolves to become ever more powerful in its degradation of that flow of energy? With **MppLab** I seek insight into some of these questions.

**MAXIMUM POWER PRINCIPLE (MPP)** - It is clear that, when isolated and left alone, all systems die, run down, erode, decay and/or dissipate their matter and energy. This process is closely associated with the phenomenon of entropy production, and the 2nd law of thermodynamics (sometimes referred to as the maximum entropy principle, or MEP) easily describes how this happens. Any such energetically isolated system automatically alters and reconfigures itself, moving through a series of ever more probable states along a trajectory of ever increasing entropy, until a most probable configuration or state of maximal entropy is achieved. This state of maximal entropy is usually characterized by an excess of sameness, a lack of structures, shapes or spatial variations, and by characteristic distributions of energies among the parts. Once having achieved such a configuration, the isolated system then remains in a state of maximal entropy (a most probable state) forever after. However, when we look around ourselves, virtually everything we see is characterized by remarkable improbable variety, a plethora of structures and shapes, and turbulent distributions of energy. Clearly, when a system is not isolated and left alone, there is another dynamic able to overpower the 2nd law and undo its nasty work. Such is the nature of the proposed 4th law of thermodynamics. A.J. Lotka, H.T. Odum and R.C. Pinkerton called this the Maximum Power Principle (MPP). H.T. Odum (1924-2002) went on, over four decades, to argue that the MPP is the best candidate for the fourth law of thermodynamics, having explanatory value for such things as ecosystems, economies, and other self-organizing systems. However, in spite of the fact that there is plenty of anecdotal evidence in support of the concept, it remains little understood, and little studied it seems. The MPP says (my words) that any self-organizing system that is open with respect to a flow of energy will configure itself to store/consume/use energy at the maximum rate possible. This model is a "laboratory" in which I can study the nature of the MPP.

**Atwood's Machine** - The approach in **OamLab** and **MppLab** is to study the Lotka/Odum MPP using a marvelous gizmo called Atwood's Machine (AM). This machine was invented in 1784 by the English mathematician George Atwood for the study of Newton's laws of motion. It has since become a common device in the design of a variety of lifts which use counterweights. Odum and Pinkerton used the AM as an example in their 1955 study of the MPP. In a variety of diary notes that I have written in an attempt to understand the MPP, I have developed a rather arcane notation of OAMs, HOAMs and OAM chains. It is highly recommended that interested people read those notes prior to studying this model. They are summarized below.

**SUSTAINABLE ECONOMICS** - **MppLab** is being written as part of a personal study of the dynamics of a sustainable economy. It has become clear to me that a modern economy is a sterling example of a system that has evolved to extract matter and energy from its environment, and to degrade and disperse those resources at a maximal rate. That observation has led to the study of the MPP. During the course of that study I have become aware that there are two principles that have been consistently proposed by scientists as candidates for the fourth law of thermodynamics. One is the MPP, as described above. The other is often referred to as the Maximum Entropy Production Principle (or MEPP). Note that this goes beyond the 2nd law - the MEP. The MEPP says (my words) that any self-organizing system that is open with respect to a flow of energy will configure itself to continuously **produce** entropy at the maximum rate possible. Now, I have intentionally reworded the two principles to draw attention to the similarity. I believe I have not mangled either idea too badly. I am personally convinced of two things:

- The MPP and the MEPP are two sides of a single little-understood phenomenon, and in both cases the proponents argue that these laws play a significant role in the organization of both ecosystems and economic systems. In these days of daily news of ecological and economic perils, it seems we might want to put some effort into understanding such a phenomenon. And so, my study of economics has taken an unexpected turn towards the MPP and the MEPP for a while.

- The very same phenomenon that is actively shaping our ecological and economic destinies is also active in many agent-based models (ABMs). I am NOT saying that I believe they are simulated in ABMs. I believe they are the organizing phenomena that cause unexpected emergent behaviour in ABMs. These principles are exhibited, or can be exhibited, in ABMs. What better place to study them, then, than in ABMs?

**Atwood's Machine Understood** - I will here provide a description of an AM that will help you understand the **OamLab** and **MppLab** applications. This differs only in mechanical design from other descriptions you will find, but not in function. An AM consists of two masses, one heavy and one light, coupled by a rope that is hung over a pair of non-leveraging simple pulleys. Most descriptions show a single pulley. I prefer to view it as a pair of pulleys, because I am going to split the AM into two halves, and each half has a pulley, a mass, an energy sink, a rope to couple masses together when needed, and a hold/release latch that can be used to pin the mass in place after it has been raised. In the AM, the heavy mass is primed with gravitational potential energy as it is raised a distance D off of the floor and latched in place. It is then coupled, using the ropes, to the lighter mass that rests on the floor, as a counterweight. When the heavy mass is released, it glides slowly to the floor as the lighter counterweight mass slowly rises. When the lighter mass has risen a distance of D, it is latched in place. At that point, the two masses may again be uncoupled.

I apologize for the use of a variety of acronyms in the following explanation, and in the interface of the model, and in the code, but without them I find I get really tangled up in my words. So, here is a list of the acronyms that are important. For more detail, read the notes mentioned below in the reference section:

- **AM - Atwood's Machine in its original design** - a mechanical system that is closed with respect to energy, in the sense that most analyses of the original system start with the heavy mass already raised, and do not consider how the energy is first put into it. I use the AM as a metaphor for time-regulated transformation of energy. According to Odum, all energy-driven changes require time to unfold, and I am using the mechanics of a mechanical system to stand in as a time-based speed regulator for the biomechanical and biochemical changes that might happen as energy is passed from predator to prey in an ecosystem. I am using the well-understood mechanics of the AM to model the biochemistry of digestion.

- **OAM - Open Atwood's Machine** - an imaginary version of the AM that is open with respect to energy, allowing a flow of energy into the system on the right, and out again on the left, as it runs its course.

- **HOAM - Half of an OAM** - two of which remain when an OAM has its masses uncoupled and it is split in half. Each half consists of, as stated above, a pulley, a rope, a mass, an energy sink (the floor), and a hold-release latch that can be used to pin the mass up off of the floor.

- **RH-HOAM** - An HOAM that has been linked to the right side of another HOAM to form an OAM. The RH-HOAM must have a mass larger than the mass in its counterpart.

- **LH-HOAM** - An HOAM that has been linked to the left side of another HOAM to form an OAM. The LH-HOAM must have a mass lighter than the mass in its counterpart.

- **Chain of HOAMs** - a series of HOAMs formed into a distinct chain. They are linkable in pairs to form OAMs such that each side-by-side pair of HOAMS can form a well-formed OAM. Energy can flow into the head of the chain, and, as OAMs are formed, and as the masses are coupled and uncoupled, the energy flows through the chain to the tail. Each HOAM may be uncoupled, coupled as an RH-HOAM, or coupled as an LH-HOAM. You can think of such a chain as a simulation of energy flow through a trophic chain (along one chain in a web), of energy flow through the organic molecules that make up the cytoplasm in a cell, or, possibly, of capital flows through a supply chain of economic agents in an economy. [This is the crazy concept I am chasing in my study of sustainable economics.]

- **Web of HOAMs** - a collection of free-moving HOAMs that are freely linkable to other HOAMs with which they come in contact. They link in pairs to form OAMs such that each side-by-side pair of HOAMS forms a well-formed OAM. Energy flows from HOAM to HOAM as the masses are coupled, forming OAMs, and uncoupled again. Ultimately, the energy flows through the web. Each HOAM may exist in uncoupled form, coupled as an RH-HOAM, or coupled as an LH-HOAM. You can think of such a web as an analogy of energy flowing through an ecosystem, of energy flowing through the organic molecules that make up the cytoplasm in a cell, or, possibly, of capital flowing through independent economic agents in an economy. [This is the crazy concept I am chasing in my study of sustainable economics.]

In **OamLab** I present preformed and persistent chains of OAMs competing for survival. In **MppLab** there are free-swimming HOAMs that form OAMs at will and so make virtual chains of OAMs of fleeting existence as the HOAMs compete for survival and devour one another in that competition.

Other variable names, short forms and acronyms are indicated in brackets at the moment when they are first used, as I did with the acronyms MPP and MEPP above.

I do not intend to imply, at all, that I think self-organizing systems contain explicit chains of HOAMs, as are exhibited in **OamLab**, or even free-floating HOAMs, as are exhibited in this model. I think that, if this MPP concept contains any real useful insight, then HOAMs exist as organic molecules, organisms, and economic agents that link temporarily and exchange energy or capital via some time-regulated process. As the energy (or capital) flows through such systems from component to component, some is degraded and exhausted, while the rest is passed on down the chain. **OamLab** was a first simple laboratory. A more realistic model, say, of a trophic web, has taken some extra effort to set up. **MppLab** is the first such model of a trophic web. (See the "Omnivores" scenario.)

**Mathematics of the AM** - An AM starts with stored total gravitational potential energy (**Wt**) equal to the acceleration due to gravity (**g**) times the heavier mass (**Mh**) times the distance from the mass to the floor (**D**). We write that as **Wt** = **g** x **D** x **Mh**. After **Mh** is released, and as the AM runs to completion, this energy is transformed in two ways. The coupled mass assembly accelerates, and picks up kinetic energy. At the same time, the lighter mass (**Ml**) is raised off the floor by a distance **D**, gaining gravitational potential energy (**Wu**) according to the equation **Wu** = **g** x **D** x **Ml**. When **Mh** strikes the floor, the kinetic energy of both masses is dissipated into the heat sink. In my language, the energy is either transferred from the RH-HOAM to the LH-HOAM as stored high-grade gravitational potential energy, or exhausted as low-grade waste heat. No entropy is produced as **Wu** is transferred and stored. Entropy is produced as the waste energy (**We**) is exhausted. **We** = **Wt** - **Wu**. Odum defines the efficiency (**Eu**) of the AM in transferring and storing high-grade energy as **Eu** = **Wu** / **Wt**, which simplifies to **Eu** = **Ml** / **Mh**.

When **Ml** << **Mh** then **Eu** is close to zero, **Mh** falls quickly, and the time-to-drop is short. This baseline value of time-to-drop (**Tb**) is given by the formula **Tb** = (2 x **D** / **g** )^0.5. Most of the initial endowment of gravitational potential energy is transformed to waste heat, and cannot be passed on to other OAMs. When **Mh** is just slightly larger than **Ml**, then it descends very very slowly, the time-to-drop is long, and most of the endowment of energy is transformed into useful energy, stored in the LH-HOAM. Curiously, the fastest transfer of the endowment of energy to still useful energy in the LH-HOAM occurs when **Eu** has a value of 1/2. That is, maximum useful power happens when **Mh** = 2 x **Ml**. [ NOTE: there is an exception to that, sometimes, when it converges to 0.618, as happens in **OamLab**.]

**Antithesis within the MPP** - Every system that captures and consumes energy can be viewed as functioning dynamically at two or more levels - at the level of the system as a whole, and at the level of the component parts. The dynamics that are encapsulated in this acronym MPP has two apparently contradictory effects. It both maximizes and minimizes the rate of entropy production, all at the same time. At the level of the system-as-a-whole, the rate of entropy production is maximized. But, at the level of the system components, as energy is transferred from component to component, average rate of entropy production is minimized during transfers. I believe that the interaction of these two opposing dynamics is the source of rising complexity.

- **Huh?** - The MPP says that this model system (which consists of many generalized HOAMs) will configure itself in such a way that two things will happen. At the lower level, the temporary OAMs, as they form, will come to operate, on average, at maximum useful power, which will occur at some intermediate level of efficiency. The rate of production of entropy in HOAM-to-HOAM transfers will be minimized. At the same time, the model as-a-whole will self-organize to capture and degrade as much energy as possible. The number of consumers (population of heterotrophs) will rise to capture as much energy as possible. The lengths of the trophic chains will extend as long as possible to effectivly consume, or degrade, as much of that energy as possible.

- So, for example, when a frog (HOAM) eats a fly (HOAM), the process of capture and digestion (temporary formation of an OAM) will transfer still useful energy from the fly to the frog at a maximum achievable rate. According to the expectations in this model, 50% of the energy in the fly will still be useful, while 50% of that energy will be degraded and discarded as waste heat. These two species will co-evolve such that there is a maximal power of the flow of non-degraded energy across this link of the trophic chain. But the system as a whole will evolve to produce waste heat at a maximum rate consistent with resource constraints (i.e. at carrying capacity of the ecosystem).

- **Um. OK, but?** - Another vision of the MPP puts it this way. In every self-organizing system there are processes that gather and process energy. Through a kind of Darwinian process of natural selection, those processes that transfer the useful energy down the chain at the highest rate persist, and will prevent the less effective processes from persisting. However, by the time some fraction of the useful energy at last reaches the end of the chain, it is all ultimately degraded and discarded and no longer useful. The ever evolving decomposers and detrivores see to that. And so the system evolves (reconfigures itself) such that it is capturing and processing and degrading energy at maximum power.

- So we get these two opposing dynamics. At the lower level, the production of entropy is minimized (maximum power of useful energy), while at the highest level, the production of entropy of the system itself is maximized (maximum power of consumption).

As species, and trophic webs, and ecosystems evolve, this oppositional dynamic gives rise to increasing power of both kinds. And it gives rise to increasing complexity.

"But", you may ask, "by what mechanism does it increase complexity, in defiance of the second law of thermodynamics?"

I believe it works like this. Random genetic mutations occur all of the time due to imperfections in the process of duplication of DNA during reproduction of organisms. Most of these accidental mutations reduce the function, and viability, and complexity of the affected offspring. However, on rare ocasions, such a mutation (a) gives the offspring a competitive advantage among its cohort, as argued by Darwin; and (b) gives the trophic chain of which it is a component a competitive advantage among its cohort of energy pathways through the system, as argued by Lotka. If that advantage arises from increased sophistication of function or other increased complexity, then that complexity persists. Such advantage will always alter the flow of energy through the trophic web, and each such increase in complexity will persist and spread throughout the web as it dominates the capture and flow of energy.

**MppLab**, then, is a model in which I can study the free formation of OAMs within a caldron of freely associating but competing HOAMs. These transient chains of HOAMs compete for the right to survival in an environment that has a limited carrying capacity. In this model, unlike **OamLab**, I do not explicitly define any fitness criteria. The time-regulated and energy-regulated workings of the mechanical AM are used as a metaphor for biomechanical processes, and the AM embodies implicit fitness criteria with respect to time and energy. Those implicit fitness criteria cause exceedingly fast evolution of the system to a weighted average efficiency, in a Darwinian competition for survival of both genes (HOAMS) and energy linkages (OAMS).

**Research Questions** - Here are my research questions for **MppLab**:

- Under what conditions does such a self-organizing system of competing HOAMs converge to a system that has an average efficiency of Eu=1/2, as predicted by the MPP?

- What system dynamics can be understood from the study of such evolving self-organizing systems?

## HOW IT WORKS

A small population of autotroph HOAMs is created and maintained throughout a run at a pre-determined target level. Whenever an autotroph is eaten, it is immediately replaced by a fully energized replacement. They form a dependable source of energy for the heterotrophs. Each autotroph has the appearance of a small daisy. The user has the ability to decide how many autotrophs will be in the scenario.

A small population of heterotrophs are also created. This population rises in number to carrying capacity (as determined by the population of autotrophs) and continues to gather energy and reproduce successfully. At carrying capacity, heterotrophs compete for energy in the autotroph population. However, since they reproduce by fission, only 50% can survive to maturity, while the remainder must die without offspring. That is what "carrying capacity" implies. Only 50% are able to reproduce, while the other 50% die without offspring. Causes of premature death (COD) include hunger, old age and predation.

There are two scenarios, each with four variations:

- Scenario: Herbivores or omnivores

- UB gene: On or off

- LB gene: On or off

The two scenarios are: (1) Herbivores, in which the heterotrophs may eat only autotrophs; and (2) Omnivores, in which heterotrophs may also eat other heterotrophs in an act of cannibalism. The four variations arise from the setting of two switches that activate two optional mutatable genes, for a possible total of three active genes in the heterotrophs' genome. The first and most important gene is the getf (an acronym for genetic energy transfer factor) - a gene that controls the speed and efficiency of energy transfer within an OAM when the heterotroph captures some prey. Heterotrophs must only hunt prey that have a getf larger than their own. The other two genes are (a) the LB gene, that controls the lower bound of the getf gene of hunted prey; and (b) the UB gene, that controls the upper bound of the getf of hunted prey. When the LB and UB genes are switched off, they play no role in prey selection. Then a heterotroph must merely hunt prey having larger getf. But, when either of these LB/UB genes is active, the heterotroph will be more selective of which prey to attack. The LB and UB genes determine a narrower range of getf values that are suitable. When these three genes are all under evolutionary pressure in an omnivore scenario, that's when a trophic web very quickly and dramatically appears, with as many as six trophic levels, and trophic chains as long as 10-12 HOAMs.

**PLEASE NOTE** - The value of the getf gene is used as a proxy for mass in an AM. Please note that the use of the mechanical dynamics of the AM as a metaphor for the biochemical dynamics of a prey-to-predator transformation of energy results in some counter-intuitive interpretation of the "proxy for mass" gene. In the AM, energy flows from the heavy mass to the light mass. But, in a prey-to-predator interaction energy usually flows from the lighter prey to the heavier predator. It helps to view it this way: the getf genes of the two organisms are just two parameters that control the rate of flow of still useful energy, and the efficiency of the transfer. The getf genes are not, and were never intended to represent the actual mass of the organisms. The transfer of energy is, then, always from large getf towards small getf. I do not model size or extent of organisms.

## HOW TO USE IT

You have heard, I suppose, of one-player games. One of my tutored students calls programs like this a zero-player game. You set the parameters, you start it, and you watch it.

There are a total of 8 different variations on two scenarios, as described above, and each of those 8 variations can be run with different random number seeds.

To perform a run of the model:

- Select one of two scenario options;

- Select a random seed;

- Click on the **Setup** button to configure the system according to the scenario chosen;

- Optionally adjust the two switches that activate the LB and UB genes;

- Click on the **Go** button.

More adventurous users might scroll to the right and find the panel of "advanced" sliders which can be used to alter a number of parameters of the model. The 'reset defaults' button found there will bring you back to ground zero if need be. Many combinations of these sliders will be immediately fatal to the population. I have not built in fail-safe code. But if you adjust them a little, you will see things happen.

## THINGS TO NOTICE

- Note the sedate speed by which the "Herbivores" scenario evolves towards a lower average efficiency. Let it run overnight and see where it goes. Then run the "Omnivores" scenario with the same parameters and note the speed at which it evolves to a lower efficiency. Let it run overnight and see where it goes.

- Run the "Omnivores" scenario and watch the panel in which the distribution of strengths of the genes is displayed in histograms. Watch the tropic levels develop in the "Getf of Heterotrophs" display, and ripple like a flag blowing in the wind.

- During a run of the "Omnivores" scenario, watch the graph that shows you the Odum efficiency by trophic level. Then go to the graph showing the distribution of efficiencies. Explain that distribution. How do you interpret these different things?

- Run the "Herbivores" scenario with the LB and UB genes deactivated, and watch the associated distributions of strengths. Then switch them on and watch the histograms that display the distributions of those genes. When they are non-phenotypic, the distribution evolves to a markedly different shape. Can you explain this?

## THINGS TO TRY

- **SEEDS** - Note the behaviour of the system for the same scenario that differ only by different random seeds.

- **EXPERIMENTATION** - Explore some of the 8 possible variant scenarios. Alter some of the advanced sliders and setup parameters, and note how the different averages and quantities react. E.g. keep your eye on drop time, bite size, EPM, RET and "Eu".

- **A VIEW INSIDE** - [ NOTE: Do not let this run for a long time. It generates very large debug log files in a short time.] This is a four step process: (Step 1) Open the command centre by clicking on the teeny tiny upwards-pointing arrow at the bottom left of the screen. (Step 2) Then when the command centre appears at the bottom of the screen, click on the 'upsize' and 'clear' buttons at the top right of the command centre. (Step 3) Then use the debug button and the associated 'chooser' (scroll the view screen to the right to find these in panel 04) to turn on debug reporting for one or all of the steps. (Step 4) Click on 'one tick'. Then scroll through the debug info that has been written into the command centre log. [Note that it also creates a log file on your hard drive.]

- **DATA EXPORT** - There are three possible ways to export data. (Method 1) Right click on any of the graphs, and choose export. (Method 2) Or, open the command centre as described above, and in the observer command line input box at the very bottom of the screen, enter the command EXPORT-WORLD "filename.CSV", where filename is a name of your choosing. I suggest, that e.g. if the model is at tick 35, the filename might be "world35.CSV". The quotes are needed. Then, use MS Excel, or a similar spreadsheet to load that file. Every piece of data in the model will be found there somewhere in the output. These files can be loaded with MS Excel. They can also be re-loaded back into **MppLab**. (Method 3) Or, you could use the tools I have built to augment those native NetLogo abilities. Press the button to export selected graphs to CSV files.

- **ALL OF THE WAY INSIDE** - There are key routines in the code that provide insight into how the model operates. Go to the code tab and search for each of these routines: f-hunt-for-prey, f-eat-or-be-eaten, f-effect-per-tick-xrg-xfer-in-oam, or f-mutate-new-heterotroph.

## EXTENDING THE MODEL

The next step in the development of this model would be profoundly interesting, but potentially more difficult to stabilize. It would also be aimed at a study of the MPP using the AM as a metaphorical time/energy regulator. In it I may have multiple species of free-swimming autotrophs and heterotrophs. It is extremely difficult to have more than one species in a freely evolving model ecosystem. The beauty of this model is that they evolve new species on their own (i.e. new distinct trophic levels). It would be interesting to learn whether, with something like the AM at its heart, a truly stable but freely evolving multi-breed ecosystem can be modelled.

## RELATED MODELS

This model is one of a series of models that have been developed as part of a personal exploration of the dynamics of sustainable economies. They include:

- **PSoup** - Written in C++, this model explores the nature of evolutionary forces in a purely biophysical economy. Based on a previous model called **Simulated Evolution** by Dr Michael Palmiter, PSoup places a number of bugs into a primordial soup and tracks their development. Offering scenarios at many levels, it demonstrates a variety of effects of evolution from simple development of effective food search patterns in the lowest levels, to development of the five main senses, genetic cross-over and sexual reproduction. The amazing observation, for me, coming out of this model was the speed and certainty of the development of complexity. Whenever a complex option was made available in the potential genetic space of the bugs, it was explored and very complex interactions between a cohort of highly varied genotypes would emerge. I also learned, from this model, that a constant flow of energy was a necessary condition for a sustainable biophysical economy, and a necessary pre-cursor for the emergence of complexity.

- **ModEco** - There are two versions of ModEco. Written in C++, the first-written version of ModEco is a hybrid economy consisting of a PSoup-like biophysical economy joined to a financial economy. In ModEco every transfer of matter and/or energy from agent to agent is facilitated by a reciprocal transfer of money. Again, as long as there is a consistent flow of energy, the economy evolves towards a steady-state biophysical condition. However, sustainability of the financial economy has proven to be a very elusive property. It was discovered that economic sustainability was only possible if profit and loss was eliminated from the financial sector, and in its place an extremely precise regime of recognition and preservation of biophysical value was instituted. The scenario that exhibited sustainability under this harsh condition was called, somewhat jokingly, the "Perpetual Motion Machine", or "**The PMM**". In more technical terms, the equilibrium achieved in the PMM is an unstable equilibrium that must be maintained by continuous external intervention.

- **ModEco and the PMM** - Written in NetLogo, this model is a replication of the C++ model, but only of the single scenario called **The PMM**. Again, three observations are clear from this model, and from the two previous models, when looking back over the common characteristics. First, the steady-state condition of any of these models demonstrates clear evidence of entropy production rising to a maximal value, and then staying there. The distributions of alleles (in **PSoup**), or of wealth (in **ModEco and The PMM**) develop and then hold shapes characteristic of the MEP, even while energy being degraded and entropy produced. Second, the emergence of complex economic organizations and inter-agent interactions seems to be an inevitable part of the evolution towards such a sustainable configuration. Third, and perhaps most important, the steady state can only be maintained by programming techniques that address the inherent instability of the equilibria associated with those steady states.

- **EiLab** - Written in C++, this model enables a rather detailed investigation of the phenomenon of rising entropy in economic models. Inspired by the work of Dragulescu and Yakovenko (2000), it implements a capital exchange model in which I could study the origins and impact of entropy production in such models. **EiLab** stands for "Entropic Index Laboratory". I like this "laboratory" approach, because I can study many scenarios, generate lots of data, and then study the data. There were a few key observations coming out of this model. First, the study of entropy in such models is highly analogous to the study of entropy by Gibbs in his development of the concepts of "Gibbs' Free Energy". Second, in spite of the similarity to entropy, as Gibbs understood it, the entropy being investigated is not thermodynamic entropy, but a purely mathematical abstraction of it which is produced by a logical system executing logical processes distinct from chemical or heat-related effects. Third, the emergence of maximum entropy distributions was inevitable in these models, but the emergence of complexity was not, implying that there may be two distinct sets of conditions causing (a) the production of entropy, and (b) the production of complexity.

- **OamLab** - Written in NetLogo, this model is one of two developed to explore more fully the phenomenon of production of complexity in economic systems. This is a continuation of my study of sustainability of economic systems. It is the more simple early member of a set of three models in which I explore the "Maximum Power Principle" as first proposed by A.J. Lotka and as developed by H.T. Odum. Both men argued that there is a need for a "fourth" law of thermodynamics, required to explain the persistent emergence of complexity. However, I found that Odum's ideas on this topic are difficult to decipher for a number of reasons. Ultimately, I found it necessary to restate his MPP as a set of three closely-related falsifiable hypotheses, and only then could I design models to test those hypotheses. **OamLab** is the first of three such models designed to test the validity of my restatement of the MPP. The prediction was that this model would evolve to a steady state in which the average efficiency was 0.5. Strangely, the steady-state average efficiency was 0.618, and not 0.5. This led to the discovery of a dispute between Odum and Silvert in the early 1980s over which of the two numbers was the correct prediction. On further investigation, it turns out that there are, in fact, two valid answers, and both results are easily validated as consistent with the MPP. So, I consider that model, simple though it be, as supporting the hypotheses of the MPP.

- **MppLab** - Written in NetLogo, this is the middle member of the trio of models exploring the validity of the MPP. This had an exciting result, as it is able to model a trophic web, in action, with from 6 to 10 trophic levels all operational at once. I have made a YouTube video using this model.

- **CmLab** - Written in NetLogo, this is another in the series of models designed to understand sustainable economics. The name is short for "Conservation of Money" Laboratory. It's another model derived from the work of Dragulescu and Yakovenko - a capital exchange model. **PSoup** is a purely biophysical economy. **ModEco** is a hybrid biophysical/financial economy. **CmLab** is a purely financial economy. **CmLab** is a capital exchange model in which bank loans are used to create money, and double-entry book-keeping is used to track it. It can provide, I think, some interesting insights into the nature of flows of money, which forms one half of a sustainable economy.

- **TpLab** - Written in NetLogo, this model is intended to explore the hypothesized phenomenon that I am calling "Teleological Pruning". I argue that the beliefs and practices of any society are "pruned" and shaped by the same evolutionary pressures that shape our genes. Our societies are therefore shaped to conform to and agree with the effects of the Maximum Power Principle. This would explain why consumerism has emerged as the most destructive and persistent form of economic activity in our highly complex modern global economy. Our global economy has become the most powerful economy ever to have existed (in terms of energy consumed per year, and possibly in terms of energy consumed per person per year). Our beliefs (e.g. the necessity of endless economic growth) and our practices (materialism and consumerism) are now aligned with this destructive social trend. In **TpLab**, social beliefs are pitted against the effects of evolutionary pressures, with interesting effects.

## CREDITS AND REFERENCES

Here's a list of formal references that were helpful to me:

- A.J.Lotka (1922) 'Contribution to the Energetics of Evolution', Proceedings of the National Academy of Sciences of the United States of America, Vol. 8, No. 6 (Jun. 15, 1922), pp. 147-151.

- A.J.Lotka (1922) 'Natural Selection as a Physical Principle', Proceedings of the National Academy of Sciences of the United States of America, Vol. 8, No. 6 (Jun. 15, 1922), pp. 151-154.

- H.T.Odum and R.C.Pinkerton (1955) 'Time's speed regulator: The optimum efficiency for maximum output in physical and biological systems ', Am. Sci., 43 pp. 331–343.Lotka Lotka, Pinkerton, Odum, Costanza, Hall.

- H.T.Odum (1971) 'Environment, Power and Society', John Wiley, New York, 336 pp.

- W.Silvert (1982) 'The theory of power and efficiency in ecology', Ecol. Modelling, 15: 159-164.

- H.T.Odum ( 1983) 'Maximum power and efficiency: a rebuttal', Ecol. Modelling, 20: 71-82.

- C.A.S Hall, J.A.Standord and R.F.Hauer (1992) 'The distribution and abundance of organsims as a consequence of energy balances along multiple environmental gradients', OIKOS 65: 377-390.

- C.A.S Hall, Ed. (1995) 'Maximum Power: The Ideas and Applications of H.T.Odum', University Press of Colorado, 393 pp.

- C.A.S Hall ' The continuing importance of maximum power', Ecological Modelling 178 (2004) 107-113.

- T.T.Cai, T.W.Olsen and D.E.Campbell 'Maximum (em)power: a foundational principle linking man and nature', Ecological Modelling 178 (2004) 115-119.

- T.T.Cai, C.L.Montague and J.S.Davis 'The maximum power principle: An empirical investigation', Ecological Modelling 190 (2006) 317-335.

Here are some less formal references:

- A recent email interchange with C.A.S Hall and D.E. Campbell has pushed me to read about the historical roots of the Maximum Power Principle, and its connection to Atwood's machine, which lead directly to the development of **OamLab**, **MppLab** and **TpLab**.

- G.H.Boyle (Dec 2014 - Jan 2015) - I have placed a number of my own diary notes on the topic of Atwood's Machine on my website. Most can also be downloaded with this model. If you want to understand why I talk about HOAMs, or how I devised the fitness criteria for **OamLab** and **MppLab**, you are most likely to find it there. http://orrery-software.webs.com/atwood-s-machine .

- Boyle, Garvin H (2002), Primordial Soup (PSoup), Application written in C++. Downloadable from http://orrery-software.webs.com/psoup.

- M. Palmiter (1989), Simulated Evolution, Application. Downloadable from http://lifesciassoc.home.pipeline.com/instruct/evolution/.

- R. Constanza (2007) - He has written a brief but thought-provoking article on the MPP at http://www.eoearth.org/view/article/154526/ .

- E. Morbius (2104) - He has pulled together a variety of other references to the MPP and shared them at this site. http://www.reddit.com/r/dredmorbius/comments/2hz2lk/darwinlotka_energy_law/

- Boyle, Garvin H (2013, March 28). ‘ModEco and the PMM - A simple physically conservative complete sustainable economy.’ (Version 2). CoMSES Computational Model Library. Retrieved from: https://www.openabm.org/model/3613/version/2

- Boyle, Garvin H (2014, June 18). ‘Sustainable Economies ModEco.’ NetLogo Modeling Commons. Retrieved from: http://modelingcommons.org/browse/one_model/4746#model_tabs_browse_info

- Boyle, Garvin H (2015, May 27). ‘Capital Exchange Models – With Investigations of Entropic Index.’ (Version 3). CoMSES Computational Model Library. Retrieved from: https://www.openabm.org/model/3860/version/3

- Boyle, Garvin H (2016). ‘Maximum Power Principle OamLab.’ NetLogo Modeling Commons.

- Boyle, Garvin H (2016, May 9). ‘Maximum Power Principle MppLab.’ Not yet released.

- Boyle, Garvin H (2016, May 9). ‘150907 MPP and Trophic Levels R1.’ Retrieved from: https://www.youtube.com/watch?v=1NsRF4Bi0Zc

- Boyle, Garvin H (2016. ‘Conservation of Money Laboratory.’ Not yet released.

Ongoing conversations with **Sholto Maud** of Australia have been extremely helpful and very encouraging.

**CONTACT ME**:

Garvin H. Boyle

Email: orrery@rogers.com

Web: http://orrery-software.webs.com/

Snail-mail: PO Box 1149, Richmond, Ontario, Canada, K0A 2Z0

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: MppLab_V1.09.nlogo
;; By Orrery Software
;; Dated: 2017-03-25
;; Author contact:
;;   Garvin H Boyle
;;   orrery@rogers.com
;;   http://orrery-software.webs.com

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

;;-----------------------------------------------------------------------------|
;; This MppLab app is a laboratory in which students can study aspects 
;;   of the Maximum Power Principle (MPP) of H.T. Odum.

;; Please note that there was one aspect of this model that has caused some
;;   confusion when I explain it.  So, I have modified the terminology within
;;   the code and in the user interface, but the logic of the code has not 
;;   changed.  The confusion arose from my "borrowing" of the mechanics of 
;;   Atwood's Machine (the AM) to model the chemistry of digestion.  In 
;;   particular, I have invented a genetic factor that I am calling the
;;   "genetic energy transfer factor", or getf for short.  The logic
;;   for doing so is as follows:
;; - Odum argued that the dynamics of the AM are a great example of the
;;   trade-off between power and efficiency that is ubiquitous and a
;;   fundamental characteristic of ALL energy transfers.  He also argued that
;;   all energy transfers take time, and that the MPP is the common time
;;   regulator.
;; - I do not have empirical data for chemical digestion of one species by
;;   another.  In fact, to simulate a real-world trophic web, I would need data
;;   for all species trying to digest all other species.  And, for each such
;;   potential transfer, I would need both efficiency and speed of all such 
;;   energy transfers.
;; - On the other hand, we have an exquisitely precise analytic description of
;;   the energy transfer that happens in the AM, providing both efficiency and
;;   power (rate of energy transfer), and implicit therein is the time required
;;   to complete the transfer (called the drop time).
;; - So, I reasoned, I could emulate the efficiency and rate of energy transfer
;;   of digestion using the analytic description of the AM.  Since the mass of
;;   the two components of the AM are the critical factors, I have inserted a
;;   proxy for mass into all organisms, and I call that the genetic-energy-
;;   transfer-factor (or getf).  Whenever two organisms meet, I use their
;;   respective getf values to determine (a) who is predator and who is prey;
;;   (b) how long it takes for predator to digest prey; and (c) how much of the
;;   consumed energy of the prey is turned to waste heat, and how much is 
;;   retained as "still-useful-energy" in the predator.
;; - This does not give me a simulation of any particular act of digestion, but
;;   it does give me a template for emulation of all possible acts of digestion
;;   (all possible efficiencies and powers) and thus allows me to investigate 
;;   the nature of real-world trophic webs.

;; So, to be clear, the concept of mass that we all know and understand as 
;;   playing a significant role in biology IS NOT EXPLICITLY USED ANYWHERE IN 
;;   THIS MODEL.
;; BUT, the ability of one organism to digest another organism is determined by
;;   the interaction of the relative values of the getf factors.
;; AND, I use the mathematics of energy transfers that derives from the AM and
;;   the masses therein to compute the effects of getf values when they
;;   interact.

;; Mass in the AM is a proxy for getf in an organism, playing similar roles in 
;;   determining the dynamics of energetic interactions.

;;-----------------------------------------------------------------------------|
;; 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: on
  ;; vertical wrap: on
  ;; location of origin: centre
  ;; patch size: 9.63 pixels
  ;;-----------------------------------------------------------------------------|
  ;; Implicit global variables due to model settings – patch locations
  ;; min-pxcor  -15
  ;; max-pxcor   15
  ;; min-pycor  -15
  ;; max-pycor   15
  
  ;;----------------------------
  ;; SCENARIO SELECTION CONTROLS
  ;;----------------------------
  
  ;; gs-scenario         ;; Chooser, string converts to a scenario number
  g-scenario-number      ;; scenario no., 0 or 1; interpretation of gs-scenario
  ;; The possible scenarios.
  ge-scenario-herbivores ;; scenario 0
  ge-scenario-omnivores  ;; scenario 1

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

  ;; Atwood's Machine parameters (Sliders)
  ;; g-drop-distance  ;; The distance a mass falls (D) in the AM.
  ;; g-acceleration   ;; Acceleration due to gravity (g).
  
  ;; Biophyscial life function parameters, autotrophs.
  ;; g-a-target-population  ;; The target carrying capacity [50, 10, 10000].
  g-a-initial-getf    ;; Initial getf (mass) of autotrophs on startup.

  ;; Biophyscial life function parameters, heterotrophs.
  gb-h-heterotrophs-on  ;; Creates heterotrophs
  g-h-initial-getf      ;; Initial getf (mass) of heterotrophs on startup.
  g-h-DAT   ;; Death Age Threshold
  ;; g-h-RET-factor     ;; Repreductive Energy Threshold Slider [0.1,0.01,1.0]
  ;; g-h-EPM-factor     ;; Energy Per Move (expended) Slider [0,.0001,.1]
  ;; g-h-ub-upper-bound ;; Upper bound on the ub gene Slider [2,.1,20]
  ;; g-h-lb-lower-bound ;; lower bound on the lb gene Slider [1,.1,4]
  ;; g-h-initial-population ;; The number of heterotrophs deployed by button.
  ;; g-h-mutation-factor    ;; delta-getf (delta-mass) Slider [0,.01,1]
  ;; g-h-satiation-factor   ;; feeding trigger Slider [0,.01,1]
  ;; gb-h-ub-gene-active ;; Switch activates ub gene for prey selection.
  ;; gb-h-lb-gene-active ;; Switch activates lb gene for prey selection.
  
    
  ;; List to hold counts of cause of death.
  gl-causes-of-death-a-per-tick
  gl-causes-of-death-a-cumulative
  gl-causes-of-death-h-per-tick
  gl-causes-of-death-h-cumulative

  ;; Global enumeration (ge-) codes codes for cause of death.
  ge-cod-none
  ge-cod-hunger
  ge-cod-fission
  ge-cod-old-age
  ge-cod-as-prey
  ge-cod-toggled

  ;; List to hold counts of cause of birth.
  gl-causes-of-birth-a-per-tick
  gl-causes-of-birth-a-cumulative
  gl-causes-of-birth-h-per-tick
  gl-causes-of-birth-h-cumulative

  ;; Global enumeration (ge-) codes for cause of birth.
  ge-cob-generated
  ge-cob-fission

  ;; Control on type of participation in OAM (b-is-in-oam).
  ;; Global enumeration (ge-) codes for status in oam.
  ge-not-in-oam                    ;; Should be assigned a zero.
  ge-rh-hoam                       ;; Should be assigned a one.
  ge-lh-hoam                       ;; Should be assigned a two.
  
  ;;-------------------------------------
  ;; 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
  ;; System of energy sinks.
  gl-sinks-per-tick
  gl-sinks-cumulative

  ;; Global enumeration (ge-) codes.
  ge-sinktype-source         ;; Xrg in, from Sun, creation/injection of agents. 
  ge-sinktype-unused-source  ;; Unused after feeding.
  ge-sinktype-a-move         ;; Autotrophs EPM
  ge-sinktype-h-move         ;; Heterotrophs EPM
  ge-sinktype-a-fiss-exergy  ;; 'Usable energy' transferred auto to D1/D2.
  ge-sinktype-h-fiss-exergy  ;; 'Usable energy' transferred hetero to D1/D2.
  ge-sinktype-a-food-exergy  ;; 'Usable energy' transferred auto to pred.
  ge-sinktype-h-food-exergy  ;; 'Usable energy' transferred hetero to pred.
  ge-sinktype-a-food-excess  ;; 'Excess food' exhausted by auto.
  ge-sinktype-h-food-excess  ;; 'Excess food' exhausted by hetero.
  ge-sinktype-a-kinetic      ;; 'Kinetic energy' exhausted by auto.
  ge-sinktype-h-kinetic      ;; 'Kinetic energy' exhausted by hetero.
  ge-sinktype-a-die-fiss     ;; Unused exergy of auto on fission.
  ge-sinktype-h-die-fiss     ;; Unused exergy of hetero on fission.
  ge-sinktype-a-die-hunger   ;; Remaining energy of auto on death.
  ge-sinktype-h-die-hunger   ;; Remaining energy of hetero on death.
  ge-sinktype-a-die-oldage   ;; Remaining energy of auto on death.
  ge-sinktype-h-die-oldage   ;; Remaining energy of hetero on death.
  ge-sinktype-a-die-asprey   ;; Remaining energy of auto on death.
  ge-sinktype-h-die-asprey   ;; Remaining energy of hetero on death.

  ;;---------------------------------------------------------------------------|
  ;; The following agent sets, counts and averages are for data collection 
  ;;   and display in monitors and plots.
  
  ;; Agent sets
  ga-oams   ;; Set of all turtles as lh-hoams
  
  ;; Counts
  g-no-of-autotrophs        ;; count of all autotrophs
  g-no-of-heterotrophs      ;; count of all heterotrophs
  g-no-of-oams              ;; count of all Open Atwood Machines
  g-no-of-a-as-rh-hoams     ;; count of all autotrophs in rh-hoams
  g-no-of-h-as-rh-hoams     ;; count of all heterotrophs in rh-hoams
  
  ;; Averages
  g-a-ave-getf              ;; getf (mass) of autotrophs
  g-a-ave-max-potential     ;; max pot of autotrophs
  g-a-ave-cur-potential     ;; current pot of autotrophs

  g-h-ave-age               ;; age of heterotrophs
  g-h-ave-getf              ;; getf (mass) of heterotrophs
  g-h-ave-lb-gene           ;; gene controlling size of prey
  g-h-ave-ub-gene           ;; gene controlling size of prey
  g-h-ave-RET               ;; RET of heterotrophs
  g-h-ave-EPM               ;; EPM of heterotrophs
  g-h-ave-max-potential     ;; max pot of heterotrophs
  g-h-ave-cur-potential     ;; current pot of heterotrophs
  g-h-ave-BITE-total        ;; average bite of heterotrophs
  g-h-ave-BITE-xrg          ;; portion to exergy
  g-h-ave-BITE-kinetic      ;; portion to kinetic energy

  g-h-ave-Eu                ;; Odum's efficiency of OAMs
  g-h-ave-max-dt            ;; maximum drop time of OAMs
  g-h-ave-cur-dt            ;; current drop time of OAMs
  g-h-ave-rem-dt            ;; remaining drop time of OAMs
  g-h-ave-dt-ratio          ;; ratio rem/max dt of OAMs

  ;; SWITCHES - These are declared in the switch itself, and so are 
  ;;   commented out here.  They are all native Booleans, having values of
  ;;   true or false.
  gb-stabilize-autotrophs      ;; Enables additional autotrophs to be sprouted.
  ;; gb-plot-data              ;; Enables plotting

  ;; Other - built-in or declared implicitly in plot interface items
  ;; See each plot design dialogue.

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

  ;; CSV means "Comma Separated Values"
  ;; 
  
  ;;---------------
  ;; 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
]


;;-----------------------------------------------------------------------------|
;; 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 ) 
   
  ;; MppLab-DETERMINED ATTRIBUTES
  ;; Nil.
]

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

;;-----------------------------------------------------------------------------|
;; Turtles and breeds
breed [ autotrophs    autotroph ]
breed [ heterotrophs  heterotroph ]

;;-----------------------------------------------------------------------------|
;; Attributes of autotrophs
autotrophs-own 
[
  ;; BUILT-IN ATTRIBUTES
  ;; who         ;; fixed id number
  ;; breed       ;; to which breed this turtle belongs [autotroph]
  ;; 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 autotroph dynamics.
  mas-who              ;; serial number of parent autotroph.
  default-colour       ;; as it says
  ;; getf is short for genetic-energy-transfer-factor, proxy for mass in the AM.
  getf                 ;; the getf (mass) in this HOAM
  cause-of-death       ;; for statistical purposes
  b-is-ready-to-die    ;; old (in age) or starved (in exergy)

  ;; An autotroph can be unassociated, or in the role of prey in an OAM, 
  ;;   i.e. as an RH-HOAM.

  ;; Unassociated dynamics.
  max-potential     ;; maximum potential energy
  cur-potential     ;; amount of high-grade gravitational potential energy
  
  ;; Associated with RH-HOAM dynamics.
  b-is-in-oam       ;; 0 = no; 1 = as RH-HOAM
  pred-who          ;; the who number of the predator, i.e. the rh-haom
  trophic-level-floated ;; trophic level of this autotroph
]

;;-----------------------------------------------------------------------------|
;; Attributes of heterotrophs
heterotrophs-own 
[
  ;; BUILT-IN ATTRIBUTES
  ;; who         ;; fixed id number
  ;; breed       ;; to which breed this turtle belongs [heterotroph]
  ;; 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 heterotroph.
  mas-who              ;; serial number of parent heterotroph.
  heterotroph-sn       ;; serial number of this heterotroph.
  age                  ;; age of this heterotroph
  default-colour       ;; as it says
  ;; getf is short for genetic-energy-transfer-factor, proxy for mass in the AM.
  getf                 ;; the getf (mass) in this heterotroph
  lb-genetic-factor    ;; gene to set lower bound on getf of prey.
  ub-genetic-factor    ;; gene to set upper bound on getf of prey.
  cause-of-death       ;; for statistical purposes
  RET                  ;; Reproductive Energy Threshold for this heterotroph
  EPM                  ;; Energy Per Move for this heterotroph

  b-is-ready-to-move      ;; 0 = no; 1 = ready to move
  b-is-ready-to-reproduce ;; mature (in age) and healthy (in exergy)
  b-is-ready-to-die       ;; old (in age) or starved (in exergy)

  ;; A heterotroph may be in a free-moving unassociated state (predator on the
  ;;   hunt), in an OAM as an RH-HOAM (captured prey), or in an OAM as a
  ;;   LH-HOAM (predatory eating prey).  Variables are layed out here to address
  ;;   four needs:
  ;; - unassociated heterotroph
  ;; - heterotroph in OAM as prey
  ;; - heterotroph in OAM as predator
  ;; - the OAM in which predator and prey are temporarily associated.
  ;;
  ;; Last two are used together.  I.e. the OAM variables are stored in the
  ;;   predator while the OAM exists.
  
  ;; Unassociated dynamics.
  max-potential
  cur-potential ;; amount of high-grade gravitational potential energy

  ;; Associated with OAM dynamics.
  b-is-in-oam           ;; 0 = no; 1 = as RH-HOAM; 2 = as LH-HOAM
  prey-who              ;; the who number of the prey, i.e. the rh-haom
  pred-who              ;; the who number of the predator, i.e. the lh-hoam
  no-of-prey-eaten      ;; the number of prey captured and eaten
  sum-of-t-plus-one     ;; an aggregator for trophic level data
  trophic-level-floated ;; trophic level of this heterotroph
  trophic-level-rounded ;; trophic level of this heterotroph

  Eu-in-oam             ;; Eu is H.T.Odum's efficiency (ML/MH)
  max-drop-time         ;; Drop time for this OAM.
  cur-drop-time         ;; Time since drop started.
  rem-drop-time         ;; Remaining drop time.
  drop-time-ratio       ;; Fraction of drop time remaining.
]

;;-----------------------------------------------------------------------------|
;; 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 model, the choosers, switches and sliders are
  ;;   always reset to the values that are known to work.  Only the chooser
  ;;   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 

;;-----------------------------------------------------------------------------|
;; 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'.
  
  ;; import-drawing "01-B OrrSW.jpg"
  
  ;; The version should be coded in this global variable to be included in
  ;;   output files.
  set gs-Version "MppLab_V1.09" 

  ;; 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 "Do-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.
  
  ;; Declare values of hidden declarations from sliders.
  LOG-TO-FILE ( "" )
  LOG-TO-FILE ( "  Do-set: ATWOOD MACHINE PARAMETERS (Sliders):" )
  LOG-TO-FILE ( word  "  Do-set: g-drop-distance - " g-drop-distance )
  LOG-TO-FILE ( word  "  Do-set: g-acceleration - "  g-acceleration )
  LOG-TO-FILE ( "" )

  LOG-TO-FILE ( "  Do-set: AUTOTROPH POPULATION PARAMETERS (Sliders):" )
  LOG-TO-FILE ( word  "  Do-set: g-a-target-population - " g-a-target-population )
  LOG-TO-FILE ( "" )

  ;; Biophysical life function parameters, autotrophs.
  set g-a-initial-getf 128 ;; Initial getf (mass) of autotrophs on startup.
  ;; g-a-target-population  ;; The target carrying capacity [50, 10, 10000].

  LOG-TO-FILE ( "  Do-set: INTERNAL AUTOTROPH PARAMETERS:" )
  LOG-TO-FILE ( word "  Do-set: g-a-initial-getf - " g-a-initial-getf )

  LOG-TO-FILE ( "" )
  LOG-TO-FILE ( "  Do-set: HETEROTROPH POPULATION PARAMETERS:" )
  
  ;; Biophysical life function parameters, autotrophs.
  set g-h-initial-getf 100 ;; Initial getf (mass) of heterotrophs on startup.
  ;; Biophysical life function parameters, heterotrophs.
  set g-h-DAT   1600       ;; Death Age Threshold
  ;; g-h-mutation-factor   ;; delta-getf (delta-mass); Slider [0,.01,1]
  ;; g-h-satiation-factor  ;; feeding trigger; Slider [0,.01,1]
  ;; g-h-ub-upper-bound    ;; Upper bound on the ub gene; Slider [2,.1,20]
  ;; g-h-lb-lower-bound    ;; lower bound on the lb gene; Slider [1,.1,4]
  
  LOG-TO-FILE ( word "  Do-set: g-h-initial-population - " g-h-initial-population )
  LOG-TO-FILE ( word "  Do-set: g-h-initial-getf - "       g-h-initial-getf )
  LOG-TO-FILE ( word "  Do-set: g-h-DAT - "                g-h-DAT )
  LOG-TO-FILE ( word "  Do-set: g-h-mutation-factor - "    g-h-mutation-factor )
  LOG-TO-FILE ( word "  Do-set: g-h-satiation-factor - "   g-h-satiation-factor )
  LOG-TO-FILE ( word "  Do-set: g-h-ub-upper-bound - "     g-h-ub-upper-bound )
  LOG-TO-FILE ( word "  Do-set: g-h-lb-lower-bound - "     g-h-lb-lower-bound )

  ;; List to hold counts of cause of death.
  set gl-causes-of-death-a-per-tick   ( n-values 6 [0] )
  set gl-causes-of-death-a-cumulative ( n-values 6 [0] )
  set gl-causes-of-death-h-per-tick   ( n-values 6 [0] )
  set gl-causes-of-death-h-cumulative ( n-values 6 [0] )
  ;; Enumeration codes for cause of death.
  set ge-cod-none     0
  set ge-cod-hunger   1
  set ge-cod-fission  2
  set ge-cod-old-age  3
  set ge-cod-as-prey  4
  set ge-cod-toggled  5
  
  ;; List to hold counts of cause of birth.
  set gl-causes-of-birth-a-per-tick   ( n-values 2 [0] )
  set gl-causes-of-birth-a-cumulative ( n-values 2 [0] )
  set gl-causes-of-birth-h-per-tick   ( n-values 2 [0] )
  set gl-causes-of-birth-h-cumulative ( n-values 2 [0] )
  ;; Enumeration codes for cause of birth.
  set ge-cob-generated 0
  set ge-cob-fission   1
  
  ;; Control on type of participation in OAM (b-is-in-oam).
  ;; These are enumeration values, having no meaning beyond the name.
  set ge-not-in-oam  0  ;; Should be assigned a zero.
  set ge-rh-hoam     1  ;; Should be assigned a one.
  set ge-lh-hoam     2  ;; Should be assigned a two.
  
  ;; System of energy sinks.
  set gl-sinks-per-tick ( n-values 20 [0] )
  set gl-sinks-cumulative ( n-values 20 [0] )
  ;; Global enumeration (ge-) variables.
  set ge-sinktype-source        0 ;; Xrg in, from Sun, creation/injection of agents. 
  set ge-sinktype-unused-source 1 ;; Unused after feeding.
  set ge-sinktype-a-move        2 ;; Autotrophs EPM
  set ge-sinktype-h-move        3 ;; Heterotrophs EPM
  set ge-sinktype-a-fiss-exergy 4 ;; 'Usable energy' transferred auto to D1/D2.
  set ge-sinktype-h-fiss-exergy 5 ;; 'Usable energy' transferred hetero to D1/D2.
  set ge-sinktype-a-food-exergy 6 ;; 'Usable energy' transferred auto to pred.
  set ge-sinktype-h-food-exergy 7 ;; 'Usable energy' transferred hetero to pred.
  set ge-sinktype-a-food-excess 8 ;; 'Excess food' transferred auto to pred.
  set ge-sinktype-h-food-excess 9 ;; 'Excess food' transferred hetero to pred.
  set ge-sinktype-a-kinetic    10 ;; 'Kinetic energy' exhausted by auto.
  set ge-sinktype-h-kinetic    11 ;; 'Kinetic energy' exhausted by hetero.
  set ge-sinktype-a-die-fiss   12 ;; Unused exergy of auto on fission.
  set ge-sinktype-h-die-fiss   13 ;; Unused exergy of hetero on fission.
  set ge-sinktype-a-die-hunger 14 ;; Remaining energy of auto on death.
  set ge-sinktype-h-die-hunger 15 ;; Remaining energy of hetero on death.
  set ge-sinktype-a-die-oldage 16 ;; Remaining energy of auto on death.
  set ge-sinktype-h-die-oldage 17 ;; Remaining energy of hetero on death.
  set ge-sinktype-a-die-asprey 18 ;; Remaining energy of auto on death.
  set ge-sinktype-h-die-asprey 19 ;; Remaining energy of hetero on death.
  
  ;;---------------------------------------------------------------------------|
  ;; The following agent sets, counts and averages are for data collection 
  ;;   and display in monitors and plots.
  
  ;; Agent sets
  set ga-oams turtles ;; Set of all turtles as lh-hoams
  
  ;; Counts
  set g-no-of-autotrophs      0  ;; count of all autotrophs
  set g-no-of-heterotrophs    0  ;; count of all heterotrophs
  set g-no-of-oams            0  ;; count of all Open Atwood Machines
  set g-no-of-a-as-rh-hoams   0  ;; count of all autotrophs in rh-hoams
  set g-no-of-h-as-rh-hoams   0  ;; count of all heterotrophs in rh-hoams
  
  ;; Averages - autotrophs
  set g-a-ave-getf            0  ;; getf (mass) of autotrophs
  set g-a-ave-max-potential   0  ;; max pot of autotrophs
  set g-a-ave-cur-potential   0  ;; current pot of autotrophs

  ;; Averages - heterotrophs
  set g-h-ave-age             0  ;; age of heterotrophs
  set g-h-ave-getf            0  ;; getf (mass) of heterotrophs
  set g-h-ave-lb-gene         0  ;; gene controlling size of prey
  set g-h-ave-ub-gene         0  ;; gene controlling size of prey
  set g-h-ave-RET             0  ;; RET of heterotrophs
  set g-h-ave-EPM             0  ;; EPM of heterotrophs
  set g-h-ave-max-potential   0  ;; max pot of heterotrophs
  set g-h-ave-cur-potential   0  ;; current pot of heterotrophs
  set g-h-ave-BITE-total      0  ;; average bite of heterotrophs
  set g-h-ave-BITE-xrg        0  ;; portion to exergy
  set g-h-ave-BITE-kinetic    0  ;; portion to kinetic energy

  ;; Averages - OAMs
  set g-h-ave-Eu              0  ;; Odum's efficiency of OAMs
  set g-h-ave-max-dt          0  ;; maximum drop time of OAMs
  set g-h-ave-cur-dt          0  ;; current drop time of OAMs
  set g-h-ave-rem-dt          0  ;; remaining drop time of OAMs
  set g-h-ave-dt-ratio        0  ;; ratio rem/max dt of OAMs

  ;; There are 3 scenarios possible
  set ge-scenario-herbivores  0  ;; Heterotrophs eat autotrophs
  set ge-scenario-omnivores   1  ;; Heterotrophs eat anything

  ;; Use the input from the chooser gs-scenario to invoke the selected scenario.
  f-set-scenario-number
  
  ;; 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: Random seed - "     g-use-this-seed )

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

  set-default-shape autotrophs  "flower"  ;; pulled from shapes library
  set-default-shape heterotrophs  "arrow" ;; pulled from shapes library

  ask patches 
  [ 
    set pcolor brown
  ]
   
  reset-ticks      ;; restarts tick counter and runs setup commands within plots

  ;; Set the switches to default setup values.
  set gb-plot-data             true ;; Enables all plotting calls.
  set gb-stabilize-autotrophs  true ;; Enables autotroph stabilization.
  set gb-h-heterotrophs-on        1 ;; Enables heterotrophs.
  set gb-h-ub-gene-active      true ;; Activates ub gene for prey selection.
  set gb-h-lb-gene-active      true ;; Activates lb gene for prey selection.

  if( g-scenario-number = ge-scenario-herbivores )
  [
    set gb-plot-data            true ;; Enables all plotting calls.
    set gb-stabilize-autotrophs true ;; Enables autotroph stabilization.
    set gb-h-heterotrophs-on       1 ;; Enables heterotrophs.
    set gb-h-ub-gene-active     true ;; Activates ub gene for prey selection.
    set gb-h-lb-gene-active     true ;; Activates lb gene for prey selection.
  ]
  if( g-scenario-number = ge-scenario-omnivores )
  [
    set gb-plot-data            true ;; Enables all plotting calls.
    set gb-stabilize-autotrophs true ;; Enables autotroph stabilization.
    set gb-h-heterotrophs-on       1 ;; Enables heterotrophs.
    set gb-h-ub-gene-active     true ;; Activates ub gene for prey selection.
    set gb-h-lb-gene-active     true ;; Activates lb gene for prey selection.
  ]
  
  f-initialize-autotrophs
  if( gb-h-heterotrophs-on = 1 )
  [
    f-initialize-heterotrophs
  ]
  
  ;; This call requires that 'reset-ticks' be called first.
  ;; 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

  ;; ASSERT ( frb-EMgr-is-valid ) ( "EMgr validity check: D-Setup" ) -1
  LOG-TO-FILE "  Do-set: procedure completed" 

  ;; end of to-setup
end 

;;-----------------------------------------------------------------------------|
;; Set the scenario number using the input from the chooser.

to f-set-scenario-number
  ;; This routine is to be executed by the observer.

  set g-scenario-number ge-scenario-herbivores  ;; default
  if( gs-scenario = "Omnivores" )
    [ set g-scenario-number ge-scenario-omnivores ]

  ;; End f-set-scenario-number
end 


;;-----------------------------------------------------------------------------|
;; Initialize a population of autotrophs.

to f-initialize-autotrophs
  ;; This routine is to be executed by the observer.

  create-autotrophs g-a-target-population 
  [ 
    f-initialize-new-autotroph 
    
    set heading 0
    
    ;; Stagger the amount of high-grade exergy from a 
    ;;   half load to a full load.
    let exergy floor( max-potential / 2 )
    set cur-potential ( exergy + ( random exergy ) ) 
    
    ;; Move each to a random point.
    setxy random-xcor random-ycor

    f-store-data-in-sink ge-sinktype-source cur-potential
    f-increment-cob-list breed ge-cob-generated
  ]

  ;; End f-initialize-autotrophs
end 

;;-----------------------------------------------------------------------------|
;; Initialize a single autotroph.

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

  ;; BUILT-IN ATTRIBUTES
  ;; who         ;; set automatically
  set heading 0  ;; direction of motion
  ;; 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
  set color green

  ;; USER-DETERMINED ATTRIBUTES
  ;; Associated with autotroph dynamics.
  set mas-who -1                 ;; serial number of parent autotroph
  set default-colour      green  ;; distinctive colour for autotrophs
  set getf     g-a-initial-getf  ;; the getf (mass) in this autotroph
  set cause-of-death ge-cod-none ;; for statistical purposes
  set b-is-ready-to-die        0 ;; old (in age) or starved (in exergy)

  ;; Recalculate the life function controls that are scaled to getf (mass).
  f-set-getf-derived-autotroph-characters

  ;; An autotroph can only be in the role of prey, i.e. RH-HOAM.
  set b-is-in-oam ge-not-in-oam ;; 0 = no; 1 = RH-HOAM
  set pred-who             -1   ;; who number of predator haom.
  set trophic-level-floated 0   ;; trophic level of this autotroph

  ;; end f-initialize-new-autotroph
end 


;;-----------------------------------------------------------------------------|
;; Calculate all of the control variables that derive from getf.

to f-set-getf-derived-autotroph-characters
  ;; This routine is to be executed by an autotroph.
  
  ;; getf is the genetic-energy-transfer-factor.  In Atwood's Machine (the AM)
  ;;   the mass of the two weights determine this.  In organisms, some aspect
  ;;   of the composition of the prey and the digestive system of the predator
  ;;   determines this.  E.g. Panda bears and bamboo go together well, but 
  ;;   panda bears and eucalyptis leaves do not.  I call this the getf.
  
  
  ;; I use the mechanics of the AM to emulate the chemistry of digestion.  This
  ;;   affects both efficiency and duration of energy transfer.
  set max-potential ( getf * g-acceleration * g-drop-distance )
  LOG-TO-FILE ( word "  Do-pre-tick: A(max-xrg) - (" floor max-potential ")" )

  ;; End of f-set-getf-derived-autotroph-characters
end 

;;-----------------------------------------------------------------------------|
;; Initialize a population of heterotrophs.

to f-initialize-heterotrophs
  ;; This routine is to be executed by the observer.

  create-heterotrophs g-h-initial-population 
  [ 
    f-initialize-new-heterotroph 
    
    let heading-list [ 0 45 90 135 180 225 270 315 ]
    let delta-heading 0
    set delta-heading ( item ( random 8 ) heading-list )
    set heading ( heading + delta-heading )

    set age ( random g-h-DAT )
    
    ;; Stagger the amount of high-grade exergy from a 
    ;;   half load to a full load.
    let exergy floor( max-potential / 2 )
    set cur-potential ( exergy + ( random exergy ) ) 
    
    f-store-data-in-sink ge-sinktype-source cur-potential
    f-increment-cob-list breed ge-cob-generated

    ;; Make one step forward - well back from prey, giving them a head start.
    forward 1
  ]

  ;; End f-initialize-heterotrophs
end 

;;-----------------------------------------------------------------------------|
;; Initialize a single heterotroph.

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

  ;; BUILT-IN ATTRIBUTES
  ;; who         ;; set automatically
  set heading 0
  ;; 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
  set color red

  ;; USER-DETERMINED ATTRIBUTES
  ;; Associated with heterotroph.
  set mas-who -1         ;; serial number of parent heterotroph
  set age              0 ;; age of this heterotroph
  set default-colour red ;; distinctive colour for heterotrophs
  set getf g-h-initial-getf ;; the getf (mass) in this heterotroph.
  set lb-genetic-factor g-h-lb-lower-bound ;; lower bound on prey getf (mass).
  set ub-genetic-factor g-h-ub-upper-bound ;; upper bound on prey getf (mass).
  set cause-of-death ge-cod-none ;; for statistical purposes

  ;; Compute value of controls scaled to getf (scaled to mass).
  f-set-getf-derived-heterotroph-characters

  ;; Set the logic trigger flags.
  set b-is-ready-to-move      1 ;; i.e. true
  set b-is-ready-to-reproduce 0 ;; i.e. false
  set b-is-ready-to-die       0 ;; i.e. false
  
  ;; Unassociated dynamics.
  set max-potential ( getf * g-acceleration * g-drop-distance )
  set cur-potential 0 ;; amount of gravitational potential energy 

  ;; Associated with OAM dynamics.
  set b-is-in-oam ge-not-in-oam ;; 0=no; 1=RH-HOAM; 2=LH-HOAM
  
  ;; Associated with OAM dynamics.
  ;; These contain data for the OAM consisting of coupled predator/prey.
  set prey-who        -1 ;; an invalid value; who number of prey haom.
  set pred-who        -1 ;; an invalid value; who number of predator haom.
  set no-of-prey-eaten      0 ;; the number of prey captured and eaten
  set sum-of-t-plus-one     0 ;; an aggregator for trophic level data
  set trophic-level-floated 1 ;; trophic level of this heterotroph
  set trophic-level-rounded 1 ;; trophic level of this heterotroph

  set Eu-in-oam        1 ;; Eu is Odum's efficiency.
  set max-drop-time    0 ;; Drop time for this OAM.
  set cur-drop-time    0 ;; Time since drop started.
  set rem-drop-time    0 ;; Remaining drop time.
  set drop-time-ratio  0 ;; Fraction of drop time remaining.

  ;; end f-initialize-new-heterotroph
end 

;;-----------------------------------------------------------------------------|
;; Calculate all of the control variables that derive from getf (mass).

to f-set-getf-derived-heterotroph-characters
  ;; This routine is to be executed by a heterotroph.
  
  ;; getf is the genetic-energy-transfer-factor.  In Atwood's Machine (the AM)
  ;;   the mass of the two weights determine this.  In organisms, some aspect
  ;;   of the composition of the prey and the digestive system of the predator
  ;;   determines this.  E.g. Panda bears and bamboo go together well, but 
  ;;   panda bears and eucalyptis leaves do not.  I call this the getf.
  
  
  ;; I use the mechanics of the AM to emulate the chemistry of digestion.  This
  ;;   affects both efficiency and duration of energy transfer.
  set max-potential ( getf * g-acceleration * g-drop-distance )
  set RET ( g-h-RET-factor * max-potential ) ;; Reproductive Energy Threshold
  set EPM ( g-h-EPM-factor * max-potential ) ;; Energy Per Move
  LOG-TO-FILE ( word "  Do-xxx: H(max-xrg,RET,EPM) - (" 
    floor max-potential "," 
    floor RET "," 
    floor EPM ")" )

  ;; End of f-set-getf-derived-heterotroph-characters
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.
  
  ;; Initialize the Pseudo Random Number Generator (PRNG).
  set g-use-this-seed 7
  
  ;; Restore the values of the lb and ub switches.
  set gb-h-ub-gene-active true
  set gb-h-lb-gene-active true
   
  ;;-----------------------------------------------
  ;; BIOPHYSICAL SUB-SYSTEM CONTROLS AND PARAMETERS
  ;;-----------------------------------------------

  ;; Slider range settings are shown as (Min,Increment,Max)
  set g-drop-distance        100       ;; ( 50,  5,   200 ) meters
  set g-acceleration           1       ;; (  1,  0.10, 12 ) m/s/s
  set g-a-target-population  500       ;; Target carrying capacity (50, 10, 10000).

  set g-h-initial-population 100       ;; # of heterotrophs (10,1,100) heterotrophs
  set g-h-RET-factor           0.95    ;; ( 0.10, 0.01, 1.00 ) Joules/Joule
  ifelse( g-scenario-number = ge-scenario-herbivores )
  [
    set g-h-EPM-factor         0.0050  ;; ( 0.00, 0.0001, 0.10 ) Joules/Joule
  ]
  ;; Else
  [
    set g-h-EPM-factor         0.0125  ;; ( 0.00, 0.0001, 0.10 ) Joules/Joule
  ]
  set g-h-mutation-factor      0.10    ;; delta-getf; Slider (0,0.01,1)
  set g-h-satiation-factor     0.98    ;; feeding trigger; Slider (0,0.01,1)
  ;; NOTE: The satiation-factor must be greater than the RET-factor.
  set g-h-ub-upper-bound       4       ;; Upper bound on the ub gene; Slider (2,0.1,20)
  set g-h-lb-lower-bound       1       ;; lower bound on the lb gene; Slider (1,0.1,4)
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 )
  [
    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-tick." ) ]

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

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

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

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

  do-post-tick
  ;; if( frb-agents-are-all-valid = false ) 
  ;;   [ LOG-TO-FILE ( word "Agents failed validity test: Do-post-tick." ) ]
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-plot-data = 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
  ]
  ;; End else

  ;; Once the data is plotted, the per-tick counts can be cleared.
  ;; List to hold counts of cause of death.
  set gl-causes-of-death-a-per-tick   ( n-values 6 [0] )
  set gl-causes-of-death-h-per-tick   ( n-values 6 [0] )
  ;; List to hold counts of cause of birth.
  set gl-causes-of-birth-a-per-tick   ( n-values 2 [0] )
  set gl-causes-of-birth-h-per-tick   ( n-values 2 [0] )

  ;; Reset the scenario number, in case the chooser has been changed.
  f-set-scenario-number
  
  ;; Clear the per-tick data for energy sinks.
  ;; This call must happen before the autotroph population is stabilized.
  set gl-sinks-per-tick ( n-values 20 [0] )
  
  ;; Stabilize the autotroph population at the target population size.
  f-stabilize-autotroph-population
  
  ;; Re-set g-h-satiation-factor in case g-h-RET-factor has changed.
  ;; Hunger must set in at or above the cost of reproduction.
  if( g-h-satiation-factor < g-h-RET-factor )
    [ set g-h-satiation-factor ( 0.01 + precision g-h-RET-factor 2 ) ]
  if( g-h-satiation-factor >= 0.99 ) 
    [ 
      set g-h-satiation-factor 0.99 
      set g-h-RET-factor 0.98
    ]
  
  if( gb-h-heterotrophs-on = 1 )
  [
    ask heterotrophs [ set age ( age + 1 ) ]
    LOG-TO-FILE ( word "  Do-pre-tick: heterotrophs aged." )
  ]
  
  LOG-TO-FILE ( word "  Do-pre-tick: Halt at tick - " g-halt-at-tick  ) 
  LOG-TO-FILE ( word "  Do-pre-tick: Current tick - " ticks ) 

  LOG-TO-FILE "  Do-pre-tick: Routine completed."
end 

;;-----------------------------------------------------------------------------|
;; Stabilize the autotroph population
;;-----------------------------------------------------------------------------|

to f-stabilize-autotroph-population
  ;; This routine is to be executed by the observer.

  if( gb-stabilize-autotrophs = true )
  [
    let current-a-population ( count autotrophs )
    if( current-a-population < g-a-target-population )
    [
      let add-this-many ( g-a-target-population - current-a-population )
      let this-patch patch 0 0
      ask this-patch
      [
        sprout-autotrophs add-this-many
        [
          f-initialize-new-autotroph
          set heading 0

          ;; Set the amount of high-grade exergy at a full load.
          set cur-potential max-potential 

          ;; Move each to a random point.
          setxy random-xcor random-ycor

          f-store-data-in-sink ge-sinktype-source cur-potential
          f-increment-cob-list breed ge-cob-generated
        ]
      ]
    ]
  ]

  ;; End f-stabilize-autotroph-population
end 
  
;;-----------------------------------------------------------------------------|
;; D2 – do-move procedure(s)
;;-----------------------------------------------------------------------------|

to do-move
  ;; 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 = "move" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-move: Debug on; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; Implement 'arrow' behaviour from PSoup application.  I.e. a strong 
  ;;   probability of movement directly forward, and small probability of a 
  ;;   slight turn.  This represents the most effective search pattern for
  ;;   an arena that is wrapped on all sides.  Of course, it doesn't matter for
  ;;   the autotrophs that get energy from the sun, but it will matter 
  ;;   for the heterotrophs.
  
  let heading-list [ -45 0 0 0 0 0 0 0 0 45 ]

  ;; Autotrophs are plants, and normally would not move, but I don't want
  ;;   bias to leak in due to plants being stationary.  In order to ensure that
  ;;   plants are equally accessible to all heterotrophs regardless of their
  ;;   parentage or location of birth I want them to roam far from parents and
  ;;   circumstances of birth.  They must be independently discovered and eaten.

  ;; Then the heterotrophs move.
  if( gb-h-heterotrophs-on = 1 )
  [
    ;; Heterotrophs move later.  Same 'arrow' search pattern.
    ask heterotrophs
    [
      if( b-is-ready-to-move = 1 )
      [
        let delta-heading ( item ( random length heading-list ) heading-list )
        set heading ( heading + delta-heading )
        forward 1
        
        ;; The heterotroph converts some exergy to waste kinetic energy as it moves.
        f-heterotroph-expends-EPM
      ]  ;; End if( b-is-ready-to-move = 1 )
    ]  ;; End ask autotrophs

    ;; A heterotroph which is acting as lh-hoam (predator, eating) does not move
    ;;   but nevertheless expends energy on life functions.
    let feeding-predator-agentset ( heterotrophs with [b-is-in-oam = ge-lh-hoam] )
    if( count feeding-predator-agentset > 0 )
    [
      ask feeding-predator-agentset
      [
        ;; Exact the price of living from this predator.
        ;; The heterotroph converts some exergy to waste kinetic energy as it moves.
        f-heterotroph-expends-EPM
      ]  ;; End ask feeding-predator-agentset
    ]  ;; End if( count feeding-predator-agentset > 0 )
  ]  ;; End if( gb-h-heterotrophs-on = 1 )

  ;; Supressed. f-update-aggregates

  LOG-TO-FILE "  Do-move: procedure completed"
end 

;;-----------------------------------------------------------------------------|
;; A heterotroph expends EPM of energy from the appropriate pool to the sink.

to f-heterotroph-expends-EPM
  ;; This routine is to be executed by a heterotroph.

  if( ( b-is-in-oam = ge-not-in-oam ) or
      ( b-is-in-oam = ge-lh-hoam ) )
  [
    ;; When a heterotroph moves it expends energy out of the pool of exergy.
    ;; Determine if this heterotroph has sufficient energy.
    ifelse ( cur-potential >= EPM )
    [
      f-store-data-in-sink ge-sinktype-h-move EPM
      set cur-potential ( cur-potential - EPM ) 
    ]
    ;; Else
    [
      f-store-data-in-sink ge-sinktype-h-move cur-potential
      set cur-potential 0 
      set cause-of-death ge-cod-hunger
    ]
    ;; End else
    LOG-TO-FILE ( word "  Do-move: H(heading,xrg,die-flag) - (" 
      heading "," floor cur-potential "," b-is-ready-to-die ")" )
  ]
  
  if( b-is-in-oam = ge-rh-hoam )
  [
    ;; When a heterotroph is associated with a heterotroph as prey in an OAM 
    ;;   then it expends energy out of the "rh" pool of exergy (-una-).
    ;; This would only take action in parasite mode.  
    ;;  - In predator mode the autotroph is not able to move or function, 
    ;;    and essentially behaves as dead until all of the exergy is removed.  
    ;;    this is the dedault mode.
    ;;  - In parasite mode the autotroph is not able to move, but still functions
    ;;    and expends exergy during each move.
    
    ;; TODO: Leave empty until parasite mode implemented.
  ]
  
  ;; End of f-heterotroph-expends-EPM  
end 

;;-----------------------------------------------------------------------------|
;; Store data in the lists of sinks.

to f-store-data-in-sink [ sinktype value ]
  ;; This routine is to be executed by anyone.
  
  ;; Record it in the per-tick list.
  let old-value ( item sinktype gl-sinks-per-tick )
  let new-value ( old-value + value )
  set gl-sinks-per-tick ( replace-item sinktype gl-sinks-per-tick new-value )

  ;; Record it in the cumulative list.
  set old-value ( item sinktype gl-sinks-cumulative )
  set new-value ( old-value + value )
  set gl-sinks-cumulative ( replace-item sinktype gl-sinks-cumulative new-value )
end 

;;-----------------------------------------------------------------------------|
;; Increment the count in the lists of causes of death.

to f-increment-cod-list [ breedtype codtype ]
  ;; This routine is to be executed by anyone.
  
  ifelse( breedtype = autotrophs )
  [
    ;; Record it in the per-tick list.
    let old-count ( item codtype gl-causes-of-death-a-per-tick )
    let new-count ( old-count + 1 )
    set gl-causes-of-death-a-per-tick 
      ( replace-item codtype gl-causes-of-death-a-per-tick new-count )
    
    ;; Record it in the cumulative list.
    set old-count ( item codtype gl-causes-of-death-a-cumulative )
    set new-count ( old-count + 1 )
    set gl-causes-of-death-a-cumulative 
      ( replace-item codtype gl-causes-of-death-a-cumulative new-count )
  ]
  ;; Else breed is heterotrophs
  [
    ;; Record it in the per-tick list.
    let old-count ( item codtype gl-causes-of-death-h-per-tick )
    let new-count ( old-count + 1 )
    set gl-causes-of-death-h-per-tick 
      ( replace-item codtype gl-causes-of-death-h-per-tick new-count )
    
    ;; Record it in the cumulative list.
    set old-count ( item codtype gl-causes-of-death-h-cumulative )
    set new-count ( old-count + 1 )
    set gl-causes-of-death-h-cumulative 
      ( replace-item codtype gl-causes-of-death-h-cumulative new-count )
  ]
  ;; End else
end 

;;-----------------------------------------------------------------------------|
;; Increment the count in the lists of causes of birth.

to f-increment-cob-list [ breedtype cobtype ]
  ;; This routine is to be executed by anyone.
  ifelse( breedtype = autotrophs )
  [
    ;; show cobtype
    ;; Record it in the per-tick list.
    let old-count ( item cobtype gl-causes-of-birth-a-per-tick )
    let new-count ( old-count + 1 )
    set gl-causes-of-birth-a-per-tick 
      ( replace-item cobtype gl-causes-of-birth-a-per-tick new-count )
    
    ;; Record it in the cumulative list.
    set old-count ( item cobtype gl-causes-of-birth-a-cumulative )
    set new-count ( old-count + 1 )
    set gl-causes-of-birth-a-cumulative 
      ( replace-item cobtype gl-causes-of-birth-a-cumulative new-count )
  ]
  ;; Else breed is heterotrophs
  [
    ;; Record it in the per-tick list.
    let old-count ( item cobtype gl-causes-of-birth-h-per-tick )
    let new-count ( old-count + 1 )
    set gl-causes-of-birth-h-per-tick 
      ( replace-item cobtype gl-causes-of-birth-h-per-tick new-count )
    
    ;; Record it in the cumulative list.
    set old-count ( item cobtype gl-causes-of-birth-h-cumulative )
    set new-count ( old-count + 1 )
    set gl-causes-of-birth-h-cumulative 
      ( replace-item cobtype gl-causes-of-birth-h-cumulative new-count )
  ]
  ;; End else
end 

;;-----------------------------------------------------------------------------|
;; D3 – do-feed procedure(s)
;;-----------------------------------------------------------------------------|

to do-feed
  ;; 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 = "feed" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-feed: Debug on; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  if( gb-h-heterotrophs-on = 1 )
  [
    ;; Heterotrophs feed on other HOAMs.
    ;; Heterotrophs feed second.
    ask heterotrophs
    [
      ASSERT ( breed = heterotrophs ) ( "Is not heterotroph." ) who
      ;; This predator may be in one of three states:
      ;;  - Currently hunting for prey.
      ;;  - Currently eating prey.
      ;;  - Currently being eaten by another predator.
      ifelse( b-is-in-oam = ge-not-in-oam )
      [ f-hunt-for-prey ]
      ;; Else - is in oam already.
      [ f-eat-or-be-eaten ]
      ;; End Else
    ] ;; End of ask heterotrophs
  ] ;; End of if( gb-h-heterotrophs-on = 1 )
  
  ;; Supressed. f-update-aggregates

  LOG-TO-FILE "  Do-feed: procedure completed"
end 

;;-----------------------------------------------------------------------------|
;; Heterotrophs hunt for prey.

to f-hunt-for-prey
  ;; This routine is to be executed by an heterotroph.
  ;; This heterotroph is not in an oam.  It is not feeding.  It is not being
  ;;   fed upon.  It will check whether suitable prey is within reach, and,
  ;;   if yes, will form an oam as the lh-hoam, and begin feeding upon such 
  ;;   prey.
   
  ;; Is this heterotroph already satiated?  Is it hungry?
  let satiation-level ( cur-potential / max-potential )
  ;; TODO: put satiation-factor in slider.
  ifelse( satiation-level < g-h-satiation-factor ) 
  [
    ;; It is hungry.
    LOG-TO-FILE ( "  Do-feed: Hunting." )
    ;; Establish which patch it is in.
    let my-who who
    let my-getf getf
    let lb-getf ( getf * lb-genetic-factor )
    let ub-getf ( getf * ub-genetic-factor )
      
    ;; Establish a list of potential prey.
    ;; Potential prey must be mobile (i.e. not already part of an immobile
    ;;   predator-prey feeding pair, an OAM).
    ;; Potential prey must be within reach, in this patch or an immediately 
    ;;   neighbouring patch.
    ;; Potential prey must have sufficient getf (proxy-mass) to act as an 
    ;;   RH-HOAM when forming an Open Atwood's Machine.  I.e. getf > my-getf.
    ;; Organism is not a potential prey for itself.
    
    ;; Within the above restrictions, some switches or operational choices
    ;;   restrict the prey list further.
    ;; - If the scenario allows onmivores, heterotrophs may eat heterotrophs.
    ;; - If the lb gene is active, the getf of the prey must be > lb-getf.
    ;; - If the ub gene is active, the getf of the prey must be < ub-getf.

    ;; A dummy let statement.
    let prey-list []
    
    ifelse( g-scenario-number = ge-scenario-omnivores )
    [
      ;; Heterotrophs can feed on other heterotrophs or autotrophs 
      ;;   (i.e. all turtles).
      set prey-list ( ( turtles-on neighbors ) with 
        [ ( b-is-in-oam = ge-not-in-oam ) and 
          ( who != my-who ) and 
          ( getf > my-getf ) ] )

      ;; Test the lb gene.
      if( ( any? prey-list ) and ( gb-h-lb-gene-active = true ) )
        [ set prey-list ( prey-list with [getf > lb-getf] ) ]

      ;; Test the ub gene.
      if( ( any? prey-list ) and ( gb-h-ub-gene-active = true ) )
        [ set prey-list ( prey-list with [getf < ub-getf] ) ]


      ;; Select the most energetic of available prey.
      if( any? prey-list )
        [
          set prey-list ( prey-list with 
            [cur-potential = ( max [cur-potential] of prey-list ) ] )
        ]
    ]
    ;; Else herbivores
    [
      ;; Heterotrophs feed on autotrophs only.
      set prey-list ( ( autotrophs-on neighbors ) with 
        [ ( b-is-in-oam = ge-not-in-oam ) and 
          ( who != my-who ) and 
          ( getf > my-getf ) ] )

      ;; Test the lb gene.
      if( ( any? prey-list ) and ( gb-h-lb-gene-active = true ) )
        [ set prey-list ( prey-list with [getf > lb-getf] ) ]

      ;; Test the ub gene.
      if( ( any? prey-list ) and ( gb-h-ub-gene-active = true ) )
        [ set prey-list ( prey-list with [getf < ub-getf] ) ]


      ;; Select the most energetic of available prey.
      if( any? prey-list )
        [
          set prey-list ( prey-list with 
            [cur-potential = ( max [cur-potential] of prey-list ) ] )
        ]
    ]
    ;; End else Herbivores
    
    if( any? prey-list )
    [
      ;; These two HOAMs (Halves of an Open Atwood's Machine) are now coupled
      ;;   together as an Open Atwood's Machine (OAM).  Using the terminology
      ;;   of the AM, the exergy in the RH-HOAM is transformed into:
      ;;     (a) kinetic energy that will be exhausted as waste heat; and 
      ;;     (b) gravitational potential energy as the mass of the LH-HOAM 
      ;;         is raised.
      
      ;; The two HOAMs are so linked and immobile until the consumption of 
      ;;   the RH-HOAM (i.e. the prey) is completed, at which time the predator
      ;;   will continue the hunt and the prey is removed from the model.

      let prey one-of prey-list
      
      ;; The hunt is successful.
      set prey-who ( [who] of prey )
      let predator-who ( [who] of self )
      ask prey
      [
        ;; Mark this HOAM as captured prey.
        if( breed = heterotrophs )
        [
          set b-is-ready-to-move 0
        ]
        set b-is-in-oam ge-rh-hoam
        set color violet
        set pred-who predator-who
      ]
      ;; Mark this HOAM as predator.
      set b-is-ready-to-move 0
      set b-is-in-oam ge-lh-hoam
      set color yellow
      face turtle prey-who
      LOG-TO-FILE ( word "  Do-feed: Captured - " prey )
      
      ;; Adjust the trophic level data for this predator.
      set no-of-prey-eaten ( no-of-prey-eaten + 1 )
      set sum-of-t-plus-one 
        ( sum-of-t-plus-one + ( 1 + ( [trophic-level-floated] of prey ) ) )
      set trophic-level-floated ( sum-of-t-plus-one / no-of-prey-eaten )
      set trophic-level-rounded round( trophic-level-floated )
      
      ;; The predator/prey pair are now locked in an OAM.
      ;; The predator takes a first bite.
      f-effect-per-tick-xrg-xfer-in-oam
    ]
  ]  ;; End of if( g-h-satiation-factor )
  ;; Else
  [
    LOG-TO-FILE ( word "  Do-feed: Satiated!  Not hunting." )
  ]
  ;; End Else
  
  ;; End of f-hunt-for-prey
end 

;;-----------------------------------------------------------------------------|
;; Effect the exergy transfer within the OAM associated with one tick of time.

to f-effect-per-tick-xrg-xfer-in-oam
  ;; This routine is to be executed by a heterotroph, in the role of lh-hoam.
  
  ASSERT ( b-is-in-oam = ge-lh-hoam ) ( "Not an lh-hoam." ) who
  let rh-hoam ( turtle prey-who )
  let prey-breed ( [breed] of rh-hoam )
  
  ;; getf stands for genetic-energy-transfer-factor, and is a proxy for
  ;;   mass in an AM.  So "heavy" and "light" are in reference to mass.
  let heavy-mass ( [getf] of rh-hoam )
  let light-mass ( [getf] of self    )
  set Eu-in-oam ( light-mass / heavy-mass )
  let mass-total ( heavy-mass + light-mass )
  let mass-diff  ( heavy-mass - light-mass )
  
  LOG-TO-FILE ( word "    Do-feed: self - " self )
  LOG-TO-FILE ( word "    Do-feed: rh-hoam - " rh-hoam )
  LOG-TO-FILE ( word "    Do-feed: light-mass - " light-mass )
  LOG-TO-FILE ( word "    Do-feed: heavy-mass - " heavy-mass )
  LOG-TO-FILE ( word "    Do-feed: Eu-in-oam - " Eu-in-oam )
  LOG-TO-FILE ( word "    Do-feed: mass-total - " mass-total )
  LOG-TO-FILE ( word "    Do-feed: mass-diff - " mass-diff )
  
  let max-rh-potential ( [max-potential] of rh-hoam )
  let cur-rh-potential ( [cur-potential] of rh-hoam )
  let numerator ( max-rh-potential - cur-rh-potential ) 
  
  LOG-TO-FILE ( word "    Do-feed: max-rh-potential - " max-rh-potential )
  LOG-TO-FILE ( word "    Do-feed: cur-rh-potential - " cur-rh-potential )
  LOG-TO-FILE ( word "    Do-feed: numerator - " numerator )

  let mass-assembly-ratio ( mass-diff / mass-total )
  let factor ( heavy-mass * g-acceleration * g-acceleration / 2 )
  let denominator ( mass-assembly-ratio * factor )

  LOG-TO-FILE ( word "    Do-feed: mass-assembly-ratio - " mass-assembly-ratio )
  LOG-TO-FILE ( word "    Do-feed: factor - " factor )
  LOG-TO-FILE ( word "    Do-feed: denominator - " denominator )

  let time ( ( numerator / denominator ) ^ 0.5 )
  let time-plus-one ( time + 1 )
  let time-plus-two ( time + 2 )
  
  LOG-TO-FILE ( word "    Do-feed: time - " time )
  LOG-TO-FILE ( word "    Do-feed: time-plus-one - " time-plus-one )

  set max-drop-time ( ( ( 2 * g-drop-distance ) / 
      ( g-acceleration * mass-assembly-ratio ) ) ^ 0.5 ) ;; Drop time for this OAM.
  set cur-drop-time    time ;; Effective time since drop started.
  set rem-drop-time    ( max-drop-time - cur-drop-time )
  set drop-time-ratio  ( rem-drop-time / max-drop-time ) ;; Fraction of drop time remaining.

  ;; The variable 'time' is the effective time, as if this OAM had started to 
  ;;   drop with current rh potential equal to its maximum. 
  ;; Now, I need to calculate, using the discrete time OAM formulae, the
  ;;   amount of potential that is transferred/transformed in the next tick.
  let delta-rh-potential 
    ( -1 * denominator * ( ( time ^ 2 ) - ( time-plus-one ^ 2 ) ) )
  ;; The sign has been reversed to make this a positive value.
  let next-delta-rh-potential 
    ( -1 * denominator * ( ( time-plus-one ^ 2 ) - ( time-plus-two ^ 2 ) ) )
  
  LOG-TO-FILE ( word "    Do-feed: delta-rh-potential - " delta-rh-potential )

  ;; I cannot remove more potential energy than is currently there.
  if( delta-rh-potential > cur-rh-potential )
    [ set delta-rh-potential cur-rh-potential ]
  
  LOG-TO-FILE ( word "    Do-feed: delta-rh-potential - " delta-rh-potential )

  ;; Use the efficiency to break this into potential and kinetic.
  let delta-lh-potential ( Eu-in-oam * delta-rh-potential )
  let delta-oam-kinetic ( delta-rh-potential - delta-lh-potential )
  
  LOG-TO-FILE ( word "    Do-feed: delta-lh-potential - " delta-lh-potential )
  LOG-TO-FILE ( word "    Do-feed: delta-oam-kinetic - " delta-oam-kinetic )

  LOG-TO-FILE ( word "    Do-feed: (ticks,epm,bite) - (" ticks "," epm "," floor delta-lh-potential ")" )

  ;; Now, I need to transfer the appropriate potential energy to the lh-hoam.
  let available-room ( max-potential - cur-potential )
  let excess-potential 0

  LOG-TO-FILE ( word "    Do-feed: available-room - " available-room )
  LOG-TO-FILE ( word "    Do-feed: excess-potential - " excess-potential )

  if( available-room < delta-lh-potential ) 
  [ 
    ;; To maintain the rate of transformation of energy from the OAM I do not
    ;;   want to pro-rate the amount taken from the RH-HOAM down, nor do I
    ;;   want to reduce the kinetic energy exhausted.  I only want to reduce
    ;;   the amount received by the predator, and send the rest to two sinks,
    ;;   one sink for kinetic, and one for excess exergy.
    set excess-potential ( delta-lh-potential - available-room )
    set delta-lh-potential available-room 
  ]
  
  ;; Transfer the energy and expel the exhaust of both types.
  ;; Store energy in the predator.
  set cur-potential ( cur-potential + delta-lh-potential )
  ask rh-hoam
  [
    ;; Remove the energy from the prey.
    set cur-potential ( cur-potential - delta-rh-potential )
  ]
  
  ;; Send the kinetic energy to the sink now.  In a normal OAM the kinetic energy is
  ;;   not expelled to sink until MH hits the floor.  However, because I want to
  ;;   put new potential in and take it out whenever it is appropriate, so I don't
  ;;   want to hold kinetic energy for a moment that may not come in a long while.
  ;; So, I expel it immediately.
  
  ;; Exhaust kinetic energy and excess potential to appropriate sinks.
  ifelse( prey-breed = autotrophs )
  [
    ;; Prey is an autotroph.
    f-store-data-in-sink ge-sinktype-a-food-exergy delta-lh-potential
    f-store-data-in-sink ge-sinktype-a-kinetic   delta-oam-kinetic
    f-store-data-in-sink ge-sinktype-a-food-excess excess-potential
  ]
  ;; Else
  [
    ;; Prey is a heterotroph.
    f-store-data-in-sink ge-sinktype-h-food-exergy delta-lh-potential
    f-store-data-in-sink ge-sinktype-h-kinetic delta-oam-kinetic
    f-store-data-in-sink ge-sinktype-h-food-excess excess-potential
  ]
  ;; End else
  
  ;; Finally, if the prey is almost emptied, such that it is inefficient
  ;;   for the predator to continue eating, and it would be more efficient
  ;;   to release this prey and start eating another, then the prey is
  ;;   released.  The real reason for this little piece of logic is to
  ;;   ensure that there is no noise or bias introduced due to a mismatch
  ;;   of bite size and energy available in the prey.  I want every energy
  ;;   transfer, in every tick, to perfectly represent a transfer consistent
  ;;   with the dynamics of the AM.  So partial bites are not allowed.
  if( next-delta-rh-potential > ( [cur-potential] of rh-hoam ) )
  [
    f-predator-releases-prey
  ]
  
  ;; End of f-effect-per-tick-xrg-xfer-in-oam
end 

;;-----------------------------------------------------------------------------|
;; Heterotrophs eat or are eaten

to f-eat-or-be-eaten
  ;; This routine is to be executed by a heterotroph in an OAM.
  
  ;; The heterotroph is in an OAM.
  ifelse( b-is-in-oam = ge-lh-hoam )
  [
    ;; Access the prey.
    let rh-hoam ( turtle prey-who )
    let cur-rh-potential ( [cur-potential] of rh-hoam )
        
    ;; The heterotroph is in predator mode.
    if( cur-rh-potential > 0 )
    [
      ;; And there is food on the table.
      f-effect-per-tick-xrg-xfer-in-oam
    ]
  ]
  ;; Else
  [
    ;; Heterotroph is prey.  No action required.
    LOG-TO-FILE ( word "  Do-feed: Heterotroph is prey." )
  ]
  ;; End else.
  
  ;; End of f-eat-or-be-eaten
end 


;;-----------------------------------------------------------------------------|
;; D4 – do-reproduce procedure(s)
;;-----------------------------------------------------------------------------|

to do-reproduce
  ;; 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 = "reproduce" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-reproduce: Debug on; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  ;; Autotrophs come from forcible maintenance of population.
  ;;   The population is topped up with sufficient fully energized 
  ;;   autotrophs in the 'do-pre-tick' function.
  
  if( gb-h-heterotrophs-on = 1 )
  [
    ask heterotrophs
    [
      f-set-heterotroph-repro-flag
      f-reproduce-heterotroph
    ]
  ]
  
  ;; Supressed. f-update-aggregates

  LOG-TO-FILE "  Do-reproduce: procedure completed"
end 

;;-----------------------------------------------------------------------------|
;; f-set-heterotroph-repro-flag

to f-set-heterotroph-repro-flag
  ;; This routine is to be executed by a heterotroph.
  
  set b-is-ready-to-reproduce 1        ;; i.e. true
  if( cur-potential < RET )
    [ set b-is-ready-to-reproduce 0 ]  ;; i.e. false due to lack of health.
  ;; TODO: if( age < g-h-RAT )
  ;; TODO:   [ set b-is-ready-to-reproduce 0 ]  ;; i.e. false due to lack of maturity.
  if( b-is-in-oam = ge-rh-hoam ) 
    [ set b-is-ready-to-reproduce 0 ]  ;; i.e. false due to being eaten.
  
  if( b-is-ready-to-reproduce = 1 )
  [
    LOG-TO-FILE 
      ( word "  Do-reproduce: H(age,xrg,oam-flag,rep-flag) - (" 
        age "," floor cur-potential "," b-is-in-oam "," b-is-ready-to-reproduce ")" )
  ]
    
  ;; End f-set-heterotroph-repro-flag
end 

;;-----------------------------------------------------------------------------|
;; A heterotroph reproduces via fission, one mother having two daughters.

to f-reproduce-heterotroph
  ;; This routine is to be executed by a heterotroph.
  
  if( b-is-ready-to-reproduce = 1 )   ;; 1 = true
  [
    LOG-TO-FILE ( word "  Do-reproduce: Heterotroph Ma - " who )

    ;; If this heterotroph is in the process of eating prey at the moment that
    ;;   it reproduces, the prey is set free, with a total exergy equal to the
    ;;   unexpended exergy plus associated kinetic energy.
    if( b-is-in-oam = ge-lh-hoam ) [ f-predator-releases-prey ]
    
    let my-who who
    let my-exergy cur-potential
    let one-share-of-exergy floor( my-exergy / 2 )
    let excess-exergy ( my-exergy - ( 2 * one-share-of-exergy ) )
    
    let my-patch patch-here
    let mothers-getf ( [getf] of self )
    let mothers-lb-gene ( [lb-genetic-factor] of self )
    let mothers-ub-gene ( [ub-genetic-factor] of self )
    ask my-patch
    [
      sprout-heterotrophs 2
      [
        f-initialize-new-heterotroph
        ;; Note the mother of this daughter.
        set mas-who my-who
        ;; Cause the getf of this heterotroph to mutate.
        ;; Remember that getf is a proxy for mass in the AM.
        
        LOG-TO-FILE ( word "  Do-reproduce: Heterotroph Dx - " who )
        ;; Copy the getf, then mutate it.
        ;; Remember that getf is a proxy for mass in the AM.
        set getf mothers-getf
        set lb-genetic-factor mothers-lb-gene
        set ub-genetic-factor mothers-ub-gene
        f-mutate-new-heterotroph
        ;; In rare cases a mother may be full of exergy and a daughter may be
        ;;   unable to accept a full share, due to mutation of getf downwards.
        ;;   getf scales the maximum amount of energy that can be held because
        ;;   it is analogous to mass in the AM.
        let endowment-rejected 
          ( fr-heterotroph-accepts-endowment one-share-of-exergy )
        LOG-TO-FILE ( word "  Do-reproduce: endowment-rejected - " endowment-rejected )
        set excess-exergy ( excess-exergy + endowment-rejected )
        f-increment-cob-list breed ge-cob-fission
      ]
    ]
    f-store-data-in-sink ge-sinktype-h-die-fiss excess-exergy
    set cause-of-death ge-cod-fission
    ;; die  ;; The mother disappears after fission, leaving two daughters.
  ]
    
  ;; End f-reproduce-heterotroph
end 

;;-----------------------------------------------------------------------------|
;; An new heterotroph mutates, chainging the ability to store exergy or attack
;;   suitable prey.

to f-mutate-new-heterotroph
  ;; This routine is to be executed by an heterotroph.
  
  ;; First, mutate the getf (mass) that controls the ability to store exergy.
  ;; Remember that getf is a proxy for mass in the AM.
  ;; Determine whether it mutates upwards or downwards.
  let old-getf getf
  let sign ( -1 + 2 * ( random 2 ) )  ;; either a -1 or a 1.
  let delta-getf ( g-h-mutation-factor * getf * sign )
  set delta-getf ( delta-getf * ( random-float 1 ) )
  set getf ( getf + delta-getf )
  LOG-TO-FILE ( word "  Do-reproduce: Mutate getf - H(old,delta,new) - (" 
    floor old-getf "," floor delta-getf "," floor getf ")" )
  
  ;; Recalculate the life function controls that are scaled to getf (mass).
  ;; Remember that getf is a proxy for mass in the AM.
  f-set-getf-derived-heterotroph-characters
  
  ;; Next, mutate the gene that controls the minimum getf (mass) of prey.
  ;; Remember that getf is a proxy for mass in the AM.
  ;; Determine whether it mutates upwards or downwards.
  let old-gene lb-genetic-factor
  set sign ( -1 + 2 * ( random 2 ) )  ;; either a -1 or a 1.
  let delta-gene ( g-h-mutation-factor * 2.5 * sign ) ;; 2.5 = scaling factor
  set delta-gene ( delta-gene * ( random-float 1 ) )
  set lb-genetic-factor ( lb-genetic-factor + delta-gene )
  ;; If its less than one, reflect the overage above one.
  if( lb-genetic-factor < g-h-lb-lower-bound ) 
    [ set lb-genetic-factor ( ( 2 * g-h-lb-lower-bound ) - lb-genetic-factor ) ]
  LOG-TO-FILE ( word "  Do-reproduce: Mutate lb gene - H(old,delta,new) - (" 
    precision old-gene 4 "," 
    precision delta-gene 4 "," 
    precision lb-genetic-factor 4 ")" )
  
  ;; Last, mutate the gene that controls the maximum getf (mass) of prey.
  ;; Remember that getf is a proxy for mass in the AM.
  ;; Determine whether it mutates upwards or downwards.
  set old-gene ub-genetic-factor
  set sign ( -1 + 2 * ( random 2 ) )  ;; either a -1 or a 1.
  set delta-gene ( g-h-mutation-factor * 2.5 * sign ) ;; 2.5 = scaling factor
  set delta-gene ( delta-gene * ( random-float 1 ) )
  set ub-genetic-factor ( ub-genetic-factor + delta-gene )
  ;; If its more than four, reflect the overage below four.
  if( ub-genetic-factor > g-h-ub-upper-bound ) 
    [ set ub-genetic-factor ( ( 2 * g-h-ub-upper-bound ) - ub-genetic-factor ) ]
  LOG-TO-FILE ( word "  Do-reproduce: Mutate ub gene - H(old,delta,new) - (" 
    precision old-gene 4 "," 
    precision delta-gene 4 "," 
    precision ub-genetic-factor 4 ")" )
  
  ;; End of f-mutate-new-heterotroph
end 
  
;;-----------------------------------------------------------------------------|
;; An new heterotroph accepts what exergy it can.

to-report fr-heterotroph-accepts-endowment [endowment-offered]
  ;; This routine is to be executed by a heterotroph.
  
  LOG-TO-FILE ( word "  Do-reproduce: endowment-offered - " endowment-offered )
  let endowment-remaining 0
  
  ;; Calculate the maximum energy charge allowed for this heterotroph.
  ;;   Remember that getf is a proxy for mass in the AM.
  let max-exergy ( getf * g-acceleration * g-drop-distance ) 
  ;; Determine how much of the endowment this heterotroph can accept.
  let energy-to-reject ( endowment-offered - max-exergy )
  
  ;; If there is too much energy offered, reject some.  Otherwise, store all 
  ;;   of it.
  ifelse( energy-to-reject > 0 )
  [ 
    set cur-potential ( max-exergy ) 
    f-store-data-in-sink ge-sinktype-h-fiss-exergy cur-potential
    set endowment-remaining energy-to-reject
    LOG-TO-FILE ( word "  Do-reproduce: energy accepted - " max-exergy )
    LOG-TO-FILE ( word "  Do-reproduce: energy-to-reject - " energy-to-reject )
  ]
  ;; Else
  [
    set cur-potential ( endowment-offered ) 
    f-store-data-in-sink ge-sinktype-h-fiss-exergy cur-potential
    LOG-TO-FILE ( word "  Do-reproduce: energy accepted - " endowment-offered )
    set endowment-remaining 0
  ]
  ;; End else
  
  report endowment-remaining
  ;; End of fr-heterotroph-accepts-endowment
end 
  
;;-----------------------------------------------------------------------------|
;; D5 – do-die procedure(s)
;;-----------------------------------------------------------------------------|

to do-die
  ;; 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 = "die" ) )
    [ set gb-debug-flow-on 1 LOG-TO-FILE "" LOG-TO-FILE word "Do-die: Debug on; tick = " ticks ]
    [ set gb-debug-flow-on 0 ]
  ]
  
  if( ( count autotrophs ) > 0 )
  [
    ask autotrophs
    [
      f-set-autotroph-death-flag
      f-autotroph-dies
    ]
  ]
  
  if( ( count heterotrophs ) > 0 )
  [
    ask heterotrophs
    [
      f-set-heterotroph-death-flag
      f-heterotroph-dies
    ]
  ]
  
  ;; Supressed. f-update-aggregates

  LOG-TO-FILE "  Do-die: procedure completed"
end 

;;-----------------------------------------------------------------------------|
;; f-set-autotroph-death-flag

to f-set-autotroph-death-flag
  ;; This routine is to be executed by a autotroph.
  
  set b-is-ready-to-die 0        ;; i.e. false, default.

  ;; If a cause of death has already been noted, it dies.
  if( cause-of-death > ge-cod-none )
  [
    ;; A cause of death has been previously flagged.
    set b-is-ready-to-die 1 
    LOG-TO-FILE ( WORD "  Do-die: A(xrg,cod) - ("
      floor cur-potential "," cause-of-death ")" )
  ]
    
  ;; End f-set-autotroph-death-flag
end 

;;-----------------------------------------------------------------------------|
;; f-autotroph-dies

to f-autotroph-dies
  ;; This routine is to be executed by a autotroph.
  
  if( b-is-ready-to-die = 1 )
  [
    ;; If this autotroph is in the process of being eaten as prey at the 
    ;;   moment that it dies it must be released from the oam.
    if( b-is-in-oam = ge-rh-hoam ) 
    [ 
      let predator ( turtle pred-who )
      ask predator
      [
        f-predator-releases-prey 
      ]
    ]
    
    LOG-TO-FILE ( word "  Do-die: A(xrg,die-flag,cod) - (" 
      floor cur-potential "," 
      b-is-ready-to-die "," 
      cause-of-death ")" ) 

    ;; Record the cause of death in the statistics.
    if( cause-of-death > 0 )
    [
      if( cause-of-death = ge-cod-as-prey )
        [ f-store-data-in-sink ge-sinktype-a-die-asprey cur-potential ]
      f-increment-cod-list breed cause-of-death
   ]
    
    die  ;; The autotroph disappears from the system.    
  ]

  ;; End f-autotroph-dies
end 

;;-----------------------------------------------------------------------------|
;; f-set-heterotroph-death-flag

to f-set-heterotroph-death-flag
  ;; This routine is to be executed by a heterotroph.
  
  set b-is-ready-to-die 0        ;; i.e. false, default.

  ;; If a cause of death has already been noted, it dies.
  if( cause-of-death > ge-cod-none )
  [
    ;; A cause of death has been previously flagged.
    set b-is-ready-to-die 1 
    LOG-TO-FILE ( WORD "  Do-die: A(age,xrg,oam,cod) - ("
      age "," floor cur-potential "," b-is-in-oam "," cause-of-death ")" )
  ]

  ;; No cause of death has been set yet.  Check basic vital signs.
  if( cur-potential <= EPM )  ;; Effectively, this is g-h-DET.
  [ 
    set b-is-ready-to-die 1 
    set cause-of-death ge-cod-hunger 
    LOG-TO-FILE ( WORD "  Do-die: A(age,xrg,oam,cod) - ("
      age "," floor cur-potential "," b-is-in-oam "," cause-of-death ")" )
  ]
    
  if( age > g-h-DAT )
  [ 
    set b-is-ready-to-die 1 
    set cause-of-death ge-cod-old-age 
    LOG-TO-FILE ( WORD "  Do-die: A(age,xrg,oam,cod) - ("
      age "," floor cur-potential "," b-is-in-oam "," cause-of-death ")" )
  ]

  ;; If it dies as prey, that over-rides all other causes of death.
  if( ( b-is-in-oam = ge-rh-hoam ) and ( b-is-ready-to-die = 1 ) )
  [
    set cause-of-death ge-cod-as-prey 
    LOG-TO-FILE ( WORD "  Do-die: A(age,xrg,oam,cod) - ("
      age "," floor cur-potential "," b-is-in-oam "," cause-of-death ")" )
  ]
    
  ;; End f-set-heterotroph-death-flag
end 

;;-----------------------------------------------------------------------------|
;; f-heterotroph-dies

to f-heterotroph-dies
  ;; This routine is to be executed by a heterotroph.
  
  if( b-is-ready-to-die = 1 )
  [
    ;; If this heterotroph is in the process of eating prey at the moment that
    ;;   it dies, the prey is set free.
    if( b-is-in-oam = ge-lh-hoam ) 
    [ 
      f-predator-releases-prey 
    ]
    
    ;; If this heterotroph is in the process of being eaten as prey at the 
    ;;   moment that it dies it must be released from the oam.
    if( b-is-in-oam = ge-rh-hoam ) 
    [ 
      let predator ( turtle pred-who )
      ask predator
      [
        f-predator-releases-prey 
      ]
    ]
    
    LOG-TO-FILE ( word "Do-die: H(xrg,die-flag,cod) - (" 
      floor cur-potential "," 
      b-is-ready-to-die "," 
      cause-of-death ")" ) 

    ;; TODO debug cause of death.
    
    ;; Record the cause of death in the statistics.
    if( cause-of-death > 0 )
    [
      if( cause-of-death = ge-cod-hunger )
        [ f-store-data-in-sink ge-sinktype-h-die-hunger cur-potential ]
      if( cause-of-death = ge-cod-old-age )
        [ f-store-data-in-sink ge-sinktype-h-die-oldage cur-potential ]
      if( cause-of-death = ge-cod-as-prey )
        [ f-store-data-in-sink ge-sinktype-h-die-asprey cur-potential ]
      f-increment-cod-list breed cause-of-death
   ]
    
    die  ;; The heterotroph disappears from the system.    
  ]

  ;; End f-heterotroph-dies
end 

;;-----------------------------------------------------------------------------|
;; f-predator-releases-prey

to f-predator-releases-prey
  ;; This routine is to be executed by a heterotroph.
  
  ;; This heterotroph is currently eating prey.  The prey is released.
  
  let prey turtle prey-who
  ask prey
  [
    set color default-colour
    if( breed = heterotrophs )
    [
      set b-is-ready-to-move 1    ;; true
    ]
    set b-is-in-oam ge-not-in-oam
    set cause-of-death ge-cod-as-prey
  ]
  
  set color default-colour
  set b-is-ready-to-move 1    ;; true
  set b-is-in-oam ge-not-in-oam
  
  ;; Return OAM-related variables to defaults.
  ;; These contain data for the OAM consisting of coupled predator/prey.
  set prey-who        -1 ;; an invalid value; who number of prey haom.
  set pred-who        -1 ;; an invalid value; who number of predator haom.
  set Eu-in-oam        1 ;; Eu is Odum's efficiency.

  set max-drop-time    0 ;; Drop time for this OAM.
  set cur-drop-time    0 ;; Time since drop started.
  set rem-drop-time    0 ;; Remaining drop time.
  set drop-time-ratio  0 ;; Fraction of drop time remaining.


  ;; End f-predator-releases-prey
end 
;;-----------------------------------------------------------------------------|
;; D6 - do-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." ) ]
  
  ;; Update the aggregates for display in the monitors.
  f-update-aggregates

  display

  LOG-TO-FILE "  Do-post-tick: procedure completed."
end 

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



;;-----------------------------------------------------------------------------|
;; 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 may implicitly call the PRNG and
  ;;   so may 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.
  
  ;;---------------------------------------------------------------------------|
  ;; The following agent sets, counts and averages are for data collection 
  ;;   and display in monitors and plots.
  
  ;; Agent sets
  ;; Set of all turtles as lh-hoams
  set ga-oams 
    ( heterotrophs with [b-is-in-oam = ge-lh-hoam] ) 
  
  ;; Counts
  set g-no-of-autotrophs ( count autotrophs )     ;; count of all autotrophs
  set g-no-of-heterotrophs ( count heterotrophs ) ;; count of all heterotrophs
  set g-no-of-oams ( count ga-oams )  ;; count of all Open Atwood Machines
  set g-no-of-a-as-rh-hoams ( count autotrophs with [b-is-in-oam = ge-rh-hoam] )  
  set g-no-of-h-as-rh-hoams ( count heterotrophs with [b-is-in-oam = ge-rh-hoam] )  
  
  ;; Averages - autotrophs
  ifelse( g-no-of-autotrophs = 0 )
  [
    set g-a-ave-getf 0
    set g-a-ave-max-potential 0
    set g-a-ave-cur-potential 0
  ]
  ;; Else
  [
    set g-a-ave-getf ( sum [getf] of autotrophs ) / g-no-of-autotrophs
    set g-a-ave-max-potential ( sum [max-potential] of autotrophs ) / g-no-of-autotrophs
    set g-a-ave-cur-potential ( sum [cur-potential] of autotrophs ) / g-no-of-autotrophs
  ]
  ;; End else
  
  ;; Averages - heterotrophs
  ifelse( g-no-of-heterotrophs = 0 )
  [
    set g-h-ave-age 0
    set g-h-ave-getf 0
    set g-h-ave-lb-gene 0
    set g-h-ave-ub-gene 0
    set g-h-ave-RET 0
    set g-h-ave-EPM 0
    set g-h-ave-max-potential 0
    set g-h-ave-cur-potential 0
  ]
  ;; Else
  [
    set g-h-ave-age ( sum [age] of heterotrophs ) / g-no-of-heterotrophs
    set g-h-ave-getf ( sum [getf] of heterotrophs ) / g-no-of-heterotrophs
    set g-h-ave-lb-gene ( sum [lb-genetic-factor] of heterotrophs ) / g-no-of-heterotrophs
    set g-h-ave-ub-gene ( sum [ub-genetic-factor] of heterotrophs ) / g-no-of-heterotrophs
    set g-h-ave-RET ( sum [RET] of heterotrophs ) / g-no-of-heterotrophs
    set g-h-ave-EPM ( sum [EPM] of heterotrophs ) / g-no-of-heterotrophs
    set g-h-ave-max-potential ( sum [max-potential] of heterotrophs ) / g-no-of-heterotrophs
    set g-h-ave-cur-potential ( sum [cur-potential] of heterotrophs ) / g-no-of-heterotrophs
  ]
  ;; End else

  ;; Averages - OAMs
  ifelse( g-no-of-oams = 0 )
  [
    set g-h-ave-Eu 0
    set g-h-ave-max-dt 0
    set g-h-ave-cur-dt 0
    set g-h-ave-rem-dt 0
    set g-h-ave-dt-ratio 0
    set g-h-ave-BITE-total 0
    set g-h-ave-BITE-xrg 0
    set g-h-ave-BITE-kinetic 0 
  ]
  ;; Else
  [
    set g-h-ave-Eu ( sum [Eu-in-oam] of ga-oams ) / g-no-of-oams
    set g-h-ave-max-dt ( sum [max-drop-time] of ga-oams ) / g-no-of-oams
    set g-h-ave-cur-dt ( sum [cur-drop-time] of ga-oams ) / g-no-of-oams
    set g-h-ave-rem-dt ( sum [rem-drop-time] of ga-oams ) / g-no-of-oams
    set g-h-ave-dt-ratio ( sum [drop-time-ratio] of ga-oams ) / g-no-of-oams
    
    set g-h-ave-BITE-xrg  
      ( 
        ( item ge-sinktype-a-food-exergy gl-sinks-per-tick ) +
        ( item ge-sinktype-h-food-exergy gl-sinks-per-tick ) 
      ) / g-no-of-oams
    set g-h-ave-BITE-kinetic  
      ( 
        ( item ge-sinktype-a-kinetic gl-sinks-per-tick ) +
        ( item ge-sinktype-h-kinetic gl-sinks-per-tick ) 
      ) / g-no-of-oams 
    set g-h-ave-BITE-total ( g-h-ave-BITE-xrg + g-h-ave-BITE-kinetic )
  ]
  ;; End else
  
;;-----------------------------------------------------------------------------|
  ;; To ensure that the PRNG is called whether or not plots are displayed, the
  ;;   calculations needed for the histogram plots which invoke the PRNG
  ;;   implicitly should be carried out here where they will happen every tick.

;;-----------------------------------------------------------------------------|
  ;; Setup for Plot "AAAAAA"
  
  ;; This log entry may come from any step during debug operations.  
  LOG-TO-FILE "  Do-xxx: All aggregates updated."  
end 

;;-----------------------------------------------------------------------------|
;; Report the status of a switch.

to-report fr-h-lb-switch-status
  ;; This routine is to be executed by the observer.
  let answer "Non-phenotypic"
  if( gb-h-lb-gene-active = true )
  [ set answer "phenotypic" ]
  report answer  
end 

;;-----------------------------------------------------------------------------|
;; Report the status of a switch.

to-report fr-h-ub-switch-status
  ;; This routine is to be executed by the observer.
  let answer "Non-phenotypic"
  if( gb-h-ub-gene-active = true )
  [ set answer "phenotypic" ]
  report answer  
end 

;;--------------------------
;; DATA CAPTURE TO CSV FILES
;;--------------------------
  
;;-----------------------------------------------------------------------------|
;; Record the data is several selected plots to CSV files

to f-record-selected-plots
  ;; This routine is to be executed by the observer.
  
  ;; The template for the export command is:
  ;; export-plot plotname filename

  ;; Get a common timestamp for all plots.
  let timestamp fr-get-time-stamp
  
  ;; Plot 01
  let plotname "Populations"
  let plot-filename 
    ( word timestamp 
           "_Sc" g-scenario-number 
           "_Se" g-use-this-seed 
           "_Pl01_POPS.CSV" )
  export-plot plotname plot-filename
  
  ;; Plot 02
  set plotname "Ave Eu of OAMs"
  set plot-filename 
    ( word timestamp 
           "_Sc" g-scenario-number 
           "_Se" g-use-this-seed 
           "_Pl02_OAMS.CSV" )
  export-plot plotname plot-filename
  
  ;; Plot 03
  set plotname "Prey Numbers"
  set plot-filename 
    ( word timestamp 
           "_Sc" g-scenario-number 
           "_Se" g-use-this-seed 
           "_Pl03_PREY.CSV" )
  export-plot plotname plot-filename
  
  ;; Plot 04
  set plotname "Counts By T-Level"
  set plot-filename 
    ( word timestamp 
           "_Sc" g-scenario-number 
           "_Se" g-use-this-seed 
           "_Pl04_TCNTS.CSV" )
  export-plot plotname plot-filename
  
  ;; Plot 05
  set plotname "Eu By T-Level"
  set plot-filename 
    ( word timestamp 
           "_Sc" g-scenario-number 
           "_Se" g-use-this-seed 
           "_Pl05_EUBYTL.CSV" )
  export-plot plotname plot-filename
  
  ;; Plot 06
  set plotname "Max Trophic Level"
  set plot-filename 
    ( word timestamp 
           "_Sc" g-scenario-number 
           "_Se" g-use-this-seed 
           "_Pl06_MAXTL.CSV" )
  export-plot plotname plot-filename
  
  ;; End f-record-selected-plots
end 

;;-----------------------------------------------------------------------------|
;; Construct a time stamp for a file name for data in CSV format.

to-report fr-get-time-stamp
  ;; 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 time-stamp ""
  ;; Append the year as yy.
  set time-stamp word time-stamp ( substring date-string 25 27 )
  ;; Append the month as Mmm.
  set time-stamp word time-stamp fr-convert-mmm-mm ( substring date-string 19 22 )
  ;; Append the day as dd.
  set time-stamp word time-stamp ( substring date-string 16 18 )
  ;; Append a dash.
  set time-stamp word time-stamp "_"

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

  report time-stamp
  ;; End fr-get-time-stamp
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 "MppLab_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 MppLab (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 

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

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

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

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

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

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

to LOG-TO-FILE [ log-this-string ]
  ;; This routine may be executed by observer, autotroph, or heterotroph.
  ;; 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 

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

to ASSERT [ error-test error-string error-who ]
;; This routine can be run by observer, autotroph or heterotroph (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 


;;-----------------------------------------------------------------------------|
;; 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 autotrophs.
    ask autotrophs
    [
      if( frb-autotroph-is-valid = false ) [ set b-agents-are-all-valid false ]
    ]
    
    ;; Check the heterotrophs.
    ask heterotrophs
    [
      if( frb-heterotroph-is-valid = false ) [ set b-agents-are-all-valid false ]
    ]
  ]
  
  report b-agents-are-all-valid
end 

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

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

  let b-autotroph-is-valid true
  
  report b-autotroph-is-valid
end 

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

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

  let b-heterotroph-is-valid true

  if( getf < 0 ) 
  [ 
    set b-heterotroph-is-valid false 
    LOG-TO-FILE ( word "getf = " getf "; at tick = " ticks )
  ]
  

  report b-heterotroph-is-valid
end 

There are 2 versions of this model.

Uploaded by When Description Download
Garvin Boyle 14 days ago Loaded the wrong file. This fixes it. Download this version
Garvin Boyle 14 days ago Initial upload Download this version

Attached files

File Type Description Last updated
03 MppLab V1.09.png preview Preview for '03 MppLab V1.09' 14 days ago, by Garvin Boyle Download
141129 NTF - NetLogo Stds for OrrerySW R2.pdf pdf Prepared standards for Orrery Software for NetLogo projects. 14 days ago, by Garvin Boyle Download
150101 NTF Atwood's Machine R4.pdf pdf An analysis of the functioning of Atwood's Machine. 14 days 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. 14 days 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. 14 days 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. 14 days ago, by Garvin Boyle Download
160509 NTF Video of MppLab - Trophic Levels - On Youtube.pdf pdf A document with a link to a youtube video produced using MppLab. 14 days ago, by Garvin Boyle Download
170324 NTF MppLab Change Diary R4.pdf pdf The most recent change diary. 14 days ago, by Garvin Boyle Download
170326 NTF High-Level Design - MppLab R2.pdf pdf A high-level technical description of the model. 14 days ago, by Garvin Boyle Download

This model does not have any ancestors.

This model does not have any descendants.