The AHA Model  Revision: 12809
Reference implementation 04 (HEDG02_04)
m_body.f90
Go to the documentation of this file.
1 !> @file m_body.f90
2 !! The Body condition and architecture of the AHA Model.
3 !! @author Sergey Budaev <sergey.budaev@uib.no>
4 !! @author Jarl Giske <jarl.giske@uib.no>
5 !! @date 2016-2017
6 
7 !-------------------------------------------------------------------------------
8 ! $Id: m_body.f90 11233 2021-06-08 09:28:00Z sbu062 $
9 !-------------------------------------------------------------------------------
10 
11 !-------------------------------------------------------------------------------
12 !> @brief Definition the physical properties and condition of the agent
13 !> @section the_genome_module THE_BODY module
14 !> This module defines various physical properties of the agent, such as the
15 !! body size, body mass etc, as well as the condition and basic physiological
16 !! variables.
17 !! @note Note that the agent has the size property but is nonetheless
18 !! represented as a single commondata::spatial point for simplicity.
19 module the_body
20  use commondata
21  use the_environment
22  use the_hormones
23 
24  implicit none
25 
26  character (len=*), parameter, private :: modname = "(THE_CONDITION)"
27 
28  !> `CONDITION` defines the physical condition of the agent
29  type, public, extends(hormones) :: condition
30  !> The age of the agent in units of the integer time steps.
31  integer :: age
32  !> Current energy reserves, initialised non-genetically, Gaussian.
33  real(srp) :: energy_current
34  !> Maximum historical energy reserves.
35  real(srp) :: energy_maximum
36  !> Energy reserves at birth, non-genetic, Gaussian.
37  real(srp) :: energy_birth
38  !> current body length, initialised non-genetically, Gaussian, will grow.
39  real(srp) :: body_length
40  !> History stack for the body length.
41  real(srp), dimension(HISTORY_SIZE_AGENT_PROP) :: body_length_history
42  !> Body length at birth (genetically fixed), it is not used so far in the
43  !! calculations but is recorded and can be output.
44  real(srp) :: body_length_birth
45  !> This is a **control unselected** (and unused) trait that is set from
46  !! the genome as normal but is not used in any calculations. It can be
47  !! used as a control marker for random genetic drift.
48  real(srp) :: control_unselected
49  !> Current body mass, initialised calculated from length and energy
50  !! reserves.
51  real(srp) :: body_mass
52  !> History stack for body mass.
53  real(srp), dimension(HISTORY_SIZE_AGENT_PROP) :: body_mass_history
54  !> Body mass at birth, will keep record of it.
55  real(srp) :: body_mass_birth
56  !> Maximum historically body, will keep record of it.
57  real(srp) :: body_mass_maximum
58  !> Standard metabolitic rate, can change depending on hormones and
59  !! psychological state (GOS)), at birth initialised from the genome.
60  !! @note SMR is not used in this version.
61  real(srp) :: smr
62  !> Maximum stomach capacity, max. fraction of body mass available for food
63  !! here set from default value. But can change in future versions of the
64  !! model depending on the body length and the physiological state (so
65  !! specifically set for each agent rather than defined from global
66  !! parameter commondata::max_stomach_capacity_def).
67  !! @note In the old model the stomach content cannot surpass
68  !! maxstomcap=15% of agent's body mass.
69  real(srp) :: maxstomcap = max_stomach_capacity_def
70  !> Stomach content mass.
71  real(srp) :: stomach_content_mass
72  ! @warning The functions defining the growth is a quick and dirty
73  ! solution.
74  contains
75  private
76  !> Initialise the individual body condition object based on the
77  !! genome values.
78  !! See `the_body::condition_init_genotype()`
79  procedure, public :: init_condition => condition_init_genotype
80  !> This procedure enforces selective mortality of agents at birth.
81  !! See `the_body::birth_mortality_enforce_init_fixed_debug()`.
82  procedure, public :: mortality_birth => &
84  !> Cleanup the history stack of the body length and mass.
85  !! See `the_body::condition_clean_history()`
86  procedure, public :: body_history_clean => condition_clean_history
87 
88  !> Get current age.
89  !! See `the_body::condition_age_get()`
90  procedure, public :: get_age => condition_age_get
91  !> Reset the age of the agent to zero.
92  !! See `the_body::condition_age_reset_zero()`.
93  procedure, public :: age_reset => condition_age_reset_zero
94  !> Get current energy reserves.
95  !! See `the_body::condition_energy_current_get()`
96  procedure, public :: get_energy => condition_energy_current_get
97  !> Get historical maximum of energy reserves.
98  !! See `the_body::condition_energy_maximum_get()`
99  procedure, public :: get_energy_max => condition_energy_maximum_get
100  !> Get current body length.
101  !! See `the_body::condition_body_length_get()`
102  procedure, public :: get_length => condition_body_length_get
103  !> Generic interface (alias) for `get_length`.
104  generic, public :: length => get_length
105  !> Get current value of the control unselected trait.
106  !! See `the_body:condition_control_unsel_get:()`
107  procedure, public :: get_control_unselected => condition_control_unsel_get
108  !> Get current body mass.
109  !! See `the_body::condition_body_mass_get()`
110  procedure, public :: get_mass => condition_body_mass_get
111  !> Generic interface to get_mass.
112  generic, public :: mass => get_mass
113  !> Get historical record of energy reserves at birth.
114  !! See `the_body::condition_energy_birth_get()`.
115  procedure, public :: get_energ_birth => condition_energy_birth_get
116  !> Get historical record of body length at birth.
117  !! See `the_body::condition_body_length_birth_get()`
118  procedure, public :: get_length_birth => condition_body_length_birth_get
119  !> Get historical record of body mass at birth.
120  !! See `the_body::condition_body_mass_birth_get()`
121  procedure, public :: get_mass_birth => condition_body_mass_birth_get
122  !> Get historcal maximum for body mass.
123  !! See `the_body::condition_body_mass_max_get()`
124  procedure, public :: get_mass_max => condition_body_mass_max_get
125  !> Get current smr.
126  !! See `the_body::condition_smr_get()`
127  procedure, public :: get_smr => condition_smr_get
128  !> Get current stomach content.
129  !! See `the_body::condition_stomach_content_get()`
130  procedure, public :: get_stom_content => condition_stomach_content_get
131 
132  !> Increment the age of the agent by one.
133  !! See `the_body::condition_age_increment()`.
134  procedure, public :: age_increment => condition_age_increment
135  !> Set body mass optionally updating the history stack.
136  !! See `the_body::condition_body_mass_set_update_hist()`
137  procedure, public :: set_mass => condition_body_mass_set_update_hist
138  !> Set body length optionally updating the history stack.
139  !! See `the_body::condition_body_length_set_update_hist()`
140  procedure, public :: set_length => condition_body_length_set_update_hist
141  !> Calculate the visibility range of this agent. Visibility depends on
142  !! the size of the agent, ambient illumination and agent contrast.
143  !! Visibility is the distance from which this agent can be seen by a
144  !! visual object (e.g. predator or conspecific).
145  !! See `the_body::condition_agent_visibility_visual_range`.
146  procedure, public :: visibility => condition_agent_visibility_visual_range
147 
148  !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
149  ! @note `food_process_cost` can be calculated several times per time step.
150  !> Calculate the basic processing cost of catching a food item
151  !! with the mass `food_gain`. Vector-based procedure.
152  !! See `the_body::body_mass_processing_cost_calc_v()`
153  procedure, public :: food_proc_cost_v => body_mass_processing_cost_calc_v
154  !> Calculate the basic processing cost of catching a food item
155  !! with the mass `food_gain`. Object-based procedure.
156  !! See `the_body::body_mass_processing_cost_calc_o()`
157  procedure, public :: food_proc_cost_o => body_mass_processing_cost_calc_o
158  !> Generic interface to the procedures calculating the basic
159  !! processing cost of catching a food item.
160  generic, public :: food_process_cost => food_proc_cost_v, &
161  food_proc_cost_o
162 
163  !> Calculate the value of possible food gain as fitting into the agent's
164  !! stomach (or full gain if the food item fits wholly). Vector-based.
165  !! See `the_body::stomach_content_food_gain_fitting_v()`
166  procedure, public :: food_fitt_v => stomach_content_food_gain_fitting_v
167  !> Calculate the value of possible food gain as fitting into the agent's
168  !! stomach (or full gain if the food item fits wholly). Object-based.
169  !! See `the_body::stomach_content_food_gain_fitting_o()`
170  procedure, public :: food_fitt_o => stomach_content_food_gain_fitting_o
171  !> Generic interface to procedures that calculate the value of
172  !! possible food gain as fitting into the agent's stomach (or
173  !! full gain if the food item fits wholly).
174  !! See `the_body::stomach_content_food_gain_fitting_v()` and
175  !! `the_body::stomach_content_food_gain_fitting_o()`.
176  generic, public :: food_fitting => food_fitt_v, food_fitt_o
177 
178  !> Calculate extra food surplus mass non fitting into the stomach of the
179  !! agent. Vector-based.
180  !! See `the_body::stomach_content_food_gain_non_fit_v()`
181  procedure, public :: food_surpl_v => stomach_content_food_gain_non_fit_v
182  !> Calculate extra food surplus mass non fitting into the stomach of the
183  !! agent. Object-based.
184  !! See `the_body::stomach_content_food_gain_non_fit_o()`
185  procedure, public :: food_surpl_o => stomach_content_food_gain_non_fit_o
186  !> Generic interface to procedures that calculate extra food surplus
187  !! mass non fitting into the stomach of the agent.
188  generic, public :: food_surplus => food_surpl_v, food_surpl_o
189 
190  !> Do grow body mass based on food gain from a single food item adjusted
191  !! for cost etc.
192  !! See `the_body::body_mass_grow_do_calculate()`
193  procedure, public :: mass_grow => body_mass_grow_do_calculate
194  !> Do increment stomach contents with adjusted (fitted) value.
195  !! See `the_body::stomach_content_get_increment()`
196  procedure, public :: stomach_increment => stomach_content_get_increment
197 
198  !> The fraction of the cost of the processing of the food item(s)
199  !! depending on the agent SMR. It is scaled in terms of the ratio of
200  !! the food item mass to the agent mass.
201  !! See `the_body::body_mass_food_processing_cost_factor_smr()`
202  procedure, public :: cost_factor_food_smr => &
204  !> The cost of swimming of a specific distance in terms of body mass loss.
205  !! See `the_body::condition_cost_swimming_burst()`
206  procedure, public :: cost_swim => condition_cost_swimming_burst
207  !> The standard cost of swimming is a diagnostic function that shows
208  !! the cost, in units of the body mass, incurred if the agent passes a
209  !! distance equal to commondata::lifespan units of its body length.
210  !! See `the_body::cost_swimming_standard()`.
211  procedure, public :: cost_swim_std => cost_swimming_standard
212 
213  !> Update the energy reserves of the agent based on its current mass and
214  !! length.
215  !! See `the_body::condition_energy_update_after_growth()`
216  procedure, public :: energy_update => condition_energy_update_after_growth
217  !> Check if the body mass is smaller than the birth body mass or
218  !! structural body mass.
219  !! See `the_body::body_mass_is_starvation_check()`
220  procedure, public :: starved_death => body_mass_is_starvation_check
221 
222  !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
223  ! @note Procedures that are calculated at the end of the time step
224  ! of the model.
225  !> Calculate the cost of living for a single model step.
226  !! See `the_body::body_mass_calculate_cost_living_step()`
228  !> Adjust the body mass at the end of the model step against the
229  !! cost of living.
230  !! See `the_body::body_mass_adjust_living_cost_step()`
231  procedure, public :: subtract_living_cost => body_mass_adjust_living_cost_step
232  !> Calculate body length increment.
233  !! See `the_body::body_len_grow_calculate_increment_step()`
234  procedure, public :: len_incr => body_len_grow_calculate_increment_step
235  !> Do linear growth for one model step based on the above
236  !! increment function.
237  !! See `the_body::body_len_grow_do_calculate_step()`
238  procedure, public :: len_grow => body_len_grow_do_calculate_step
239  !> Do digestion. Stomach contents S(t) is emptied by a constant fraction
240  !! each time step. See details in the `stomach_content_mass_emptify_step`
241  !! function call.
242  !! See `the_body::stomach_content_mass_emptify_step()`
243  procedure, public :: stomach_empify => stomach_content_mass_emptify_step
244  !> Update the level of the sex steroids. Sex steroids are incremented
245  !! each time step of the model.
246  !! See `the_body::sex_steroids_update_increment()`
247  procedure, public :: sex_steroids_update => sex_steroids_update_increment
248 
249  end type condition
250 
251  !> `REPRODUCTION` type defines parameters of the reproduction system.
252  type, public, extends(condition) :: reproduction
253  !> Total number of reproductions during the lifespan.
254  integer :: n_reproductions
255  !> Total number of offspring reproduced during the lifespan.
256  integer :: n_offspring
257  contains
258  !> Init reproduction class.
259  !! See `the_body::reproduction_init_zero()`.
260  procedure, public :: init_reproduction => reproduction_init_zero
261 
262  !> Determine if the agent's hormonal system is ready for reproduction
263  !! See `the_body::reproduction_ready_steroid_hormones_exceed()`.
264  procedure, public :: is_ready_reproduce => &
266 
267  !> Get the number of reproductions for this agent.
268  !! See `the_body::reproduction_n_reproductions_get()`.
269  procedure, public :: get_reproductions => reproduction_n_reproductions_get
270  !> Set the number of reproductions for the agent.
271  !! See `the_body::reproduction_n_reproductions_set()`.
272  procedure, public :: reproductions_set => reproduction_n_reproductions_set
273  !> Get the number of offspring for this agent for its lifespan.
274  !! See `the_body::reproduction_n_offspring_get()`.
275  procedure, public :: get_offspring => reproduction_n_offspring_get
276  !> Set the number of offspring this agent had during its lifespan.
277  !! See `the_body::reproduction_n_offspring_set()`.
278  procedure, public :: offspring_set => reproduction_n_offspring_set
279  !> Increment the number of reproductions and offspring for the agent.
280  !! See `the_body::reproduction_n_increment()`.
281  procedure, public :: reproductions_increment => reproduction_n_increment
282  !> Calculate the number of offspring per a single reproduction.
283  !! See `the_body::reproduction_n_offspring_calc()`.
284  procedure, public :: offspring_number => reproduction_n_offspring_calc
285  !> Calculate the total mass of all offspring per single reproduction.
286  !! See `the_body::reproduction_mass_offspring_calc()`.
287  procedure, public :: offspring_mass => reproduction_mass_offspring_calc
288  !> Calculate the energetic cost of reproduction.
289  !! @note Two versions are implemented:
290  !! - `the_body::reproduction_cost_energy_fix()`
291  !! - `the_body::reproduction_cost_energy_dynamic()`
292  !! .
293  procedure, public :: reproduction_cost => reproduction_cost_energy_dynamic
294  !> Calculate the costs of unsuccessful reproduction. This is calculated
295  !! as a fraction of the normal cost of reproduction returned by the
296  !! function `reproduction::reproduction_cost()`.
297  !! See `the_body::reproduction_cost_unsuccessful_calc()`.
298  procedure, public :: reproduction_cost_unsuccess => &
300  end type reproduction
301 
302 contains ! ........ implementation of procedures for this level ................
303 
304  !> This is the function to calculate the body weight from the length and
305  !! the Fulton condition factor (energy reserves).
306  !! @param[in] k, l condition and body length.
307  !! @returns Body mass.
308  elemental function length2mass(k, l) result (body_mass)
309  real(srp), intent(in) :: k, l
310  real(srp) :: body_mass
311 
312  !> ### Implementation details ###
313  !! Body mass is non-genetic, length and initial condition factor are
314  !! genetically determined. Body mass is calculated initially from
315  !! the Fulton'scondition factor formula @f[ K=\frac{M}{L^{3}} , @f]
316  !! i.e. @f[ M=K L^{3} . @f] The exponent can be non-cube for
317  !! non-isometric growth.
318  !! @note The "cube law" exponent (3.0 normally), might be redefined here
319  !! as the LINEAR_GROWTH_EXPONENT parameter constant.
320  real(srp), parameter :: b = linear_growth_exponent
321 
322  body_mass = k * l**b
323 
324  end function length2mass
325 
326  !-----------------------------------------------------------------------------
327  !> Calculate the current energy reserves (Fulton condition factor) from body
328  !! mass and length.
329  !! @param[in] m, l body mass and body length.
330  !! @returns energy reserve available.
331  elemental function energy_reserve (m, l) result (k)
332 
333  real(srp), intent(in) :: m, l
334  real(srp) :: k
335 
336  !> @note The "cube law" exponent (3.0 normally), might be redefined here
337  !! as the LINEAR_GROWTH_EXPONENT parameter constant.
338  real(srp), parameter :: b = linear_growth_exponent
339 
340  k = m / (l**b)
341 
342  end function energy_reserve
343 
344  !-----------------------------------------------------------------------------
345  !> Initialise the individual body condition object based on the genome values.
346  !! Two alleles are selected at random and input into the `gamma2gene`
347  !! function to get the initial hormone values rescaled to 0:1. Note that
348  !! the `gamma2gene` alleles defining the **shape** of the gamma function
349  !! and the **half-max effect** are selected randomly in this version.
350  !! Also, polyploid organisms are possible, in such case, two parameters
351  !! are also randomly defined from a larger set (e.g. from four chromosomes
352  !! in case of tetraploids). See implementation details and comments for
353  !! each of the hormones.
354  subroutine condition_init_genotype(this)
355  class(condition), intent(inout) :: this
356 
357  ! PROCNAME is the procedure name for logging and debugging (with MODNAME).
358  character(len=*), parameter :: PROCNAME = "(condition_init_genotype)"
359 
360  !> ### Implementation details ###
361  !> First, initialise all the physical condition components of the
362  !! agent, starting from **age**: age=0 initially.
363  this%age = 0
364 
365  !> The **energy reserves** are set as Gaussian with the mean
366  !! commondata::energy_init and CV commondata::energy_gerror_cv.
367  this%energy_current = rnorm( energy_init, &
369  energy_init ) )
370 
371  !> Set the birth energy reserves from the initial current value.
372  this%energy_birth = this%energy_current
373 
374  !> Additionally, update the historical maximum energy value.
375  this%energy_maximum = this%energy_current
376 
377  !> The **body length** is initialised as Gaussian with the mean
378  !! commondata::body_length_init and cv commondata::body_length_gerror_cv.
379  this%body_length = rnorm( body_length_init, &
381  body_length_init ) )
382 
383  !> @note Body length cannot be zero or less than the minimum possible
384  !! size that is defined by `BODY_LENGTH_MIN`.
385  if (this%body_length < body_length_min) then
386  call log_dbg ( &
387  "WARNING: Initialised body length " // tostr(this%body_length) // &
388  " is smaller than the BODY_LENGTH_MIN in " // procname )
389  this%body_length = body_length_min
390  end if
391 
392  !> Also, body length at birth cannot reach the maximum value
393  !! `BODY_LENGTH_MAX`, if it does occurs, erroneous parameter value
394  !! was set. This aberrant agent then the_genome::individual_genome::dies().
395  if (this%body_length >= body_length_max) then
396  call log_msg( &
397  "WARNING: Initialised body length " // tostr(this%body_length) // &
398  " exceeds 1/10 BODY_LENGTH_MAX in " // procname )
399  this%body_length = body_length_max / 10.0_srp
400  call this%dies()
401  end if
402 
403  !> The historical body length at birth is saved as
404  !! the_body::condition::body_length_birth.
405  this%body_length_birth = this%body_length
406 
407  !> A **control unselected** trait is also set from the genome. This trait
408  !! is not used in any calculations but serves as a control for random or
409  !! nonrandom genetic drift.
410  call this%trait_init(this%control_unselected, &
413  control_unselected_gerror_cv, "CONTROL_UNSEL")
414 
415  !> The **body mass** is determined by the genetically determined energy
416  !! reserves and the body length (using `length2mass` function). Thus,
417  !! the body mass is **non-genetic**.
418  this%body_mass = length2mass(this%energy_current, this%body_length)
419  !> The historical body mass at birth and the maximum body mass ever
420  !! achieved are saved.
421  this%body_mass_birth = this%body_mass
422  this%body_mass_maximum = this%body_mass
423 
424  !> **SMR** is set from the genome.
425  call this%trait_init(this%smr, &
427  smr_init, smr_gerror_cv, "SMR")
428 
429  !> However, it must never be lower than commondata::smr_min. Very low
430  !! values are unrealistic and might crash model.
431  if ( this%smr < smr_min ) this%smr = smr_min
432 
433  !> **Stomach contents** is initialised as a random Gaussian value, average,
434  !! units of the body mass with `STOMACH_CONTENT_INIT` and coefficient
435  !! of variation `STOMACH_CONTENT_INIT_CV`. Stomach contents also must
436  !! always be above zero and never exceed the `maxstomcap` factor.
437  this%stomach_content_mass &
438  = min( &
439  max( zero, rnorm(this%body_mass*stomach_content_init, &
440  (this%body_mass*stomach_content_init* &
441  stomach_content_init_cv)**2) ), &
442  this%body_mass*this%maxstomcap )
443 
444  !> Finally, the procedure initialises the history stacks for the body mass
445  !! and length.
446  call this%body_history_clean()
447 
448  !> And put the initial birth values of body length and mass into the
449  !! history stack.
450  !! @note The body length and mass history stack keeps the latest historical
451  !! values.
452  call add_to_history(this%body_length_history, this%body_length)
453  call add_to_history(this%body_mass_history, this%body_mass)
454 
455  end subroutine condition_init_genotype
456 
457  !-----------------------------------------------------------------------------
458  !> This procedure enforces selective mortality of agents at birth to avoid
459  !! strong selection for energy and length.
460  !! @warning This is a debug version of the mortality procedure with fixed
461  !! mortality pattern, final should depend on the statistical
462  !! properties of the first generation, mean and sd.
464  class(condition), intent(inout) :: this
465 
466  ! htintrpl.exe [0.2 0.3 0.6 1.0] [0 0.006 0.1 1.0]
467  ! htintrpl.exe [0.2 0.3 0.5 0.8] [0 0.006 0.1 1.0]
468  real(SRP), dimension(*), parameter :: BIRTH_MORTALITY_ENERGY_ABSCISSA = &
469  [ 0.2_srp, 0.3_srp, 0.5_srp, 0.8_srp ]
470 
471  real(SRP), dimension(*), parameter :: BIRTH_MORTALITY_ENERGY_ORDINATE = &
472  [ 0.0_srp, 0.006_srp, 0.1_srp, 1.0_srp ]
473 
474  real(SRP) :: mortality
475 
476  mortality = within( ddpinterpol( birth_mortality_energy_abscissa, &
477  birth_mortality_energy_ordinate, &
478  this%energy_birth ), &
479  0.0_srp, 1.0_srp )
480 
481  if ( rand_r4() < mortality ) then
482  call this%dies()
483  end if
484 
486 
487  !-----------------------------------------------------------------------------
488  !> Cleanup the history stack of the body length and mass.
489  elemental subroutine condition_clean_history(this)
490  class(condition), intent(inout) :: this
491 
492  this%body_length_history = missing
493  this%body_mass_history = missing
494 
495  end subroutine condition_clean_history
496 
497  !=============================================================================
498  ! Accessors for the CONDITION object parameters.
499 
500  !-----------------------------------------------------------------------------
501  !> Get current age. *Standard GET-function.*
502  elemental function condition_age_get(this) result(age)
503  class(condition), intent(in) :: this
504  !> @return Return the agent's age
505  integer :: age
506 
507  age = this%age
508 
509  end function condition_age_get
510 
511  !-----------------------------------------------------------------------------
512  !> Reset the age of the agent to zero.
513  elemental subroutine condition_age_reset_zero(this)
514  class(condition), intent(inout) :: this
515 
516  this%age = 0
517 
518  end subroutine condition_age_reset_zero
519 
520  !-----------------------------------------------------------------------------
521  !> Increment the age of the agent by one.
522  elemental subroutine condition_age_increment(this, increment)
523  class(condition), intent(inout) :: this
524  !> @param[in] increment optional increment for increasing the age of the
525  !! agent, the default value is 1.
526  integer, optional, intent(in) :: increment
527 
528  if (present(increment)) then
529  this%age = this%age + increment
530  else
531  this%age = this%age + 1
532  end if
533 
534  end subroutine condition_age_increment
535 
536  !-----------------------------------------------------------------------------
537  !> Get current energy reserves. *Standard GET-function.*
538  elemental function condition_energy_current_get(this) result(energy)
539  class(condition), intent(in) :: this
540  !> @return Return the agent's energy reserves.
541  real(srp) :: energy
542 
543  energy = this%energy_current
544 
545  end function condition_energy_current_get
546 
547  !-----------------------------------------------------------------------------
548  !> Get historical maximum of energy reserves. *Standard GET-function.*
549  elemental function condition_energy_maximum_get(this) result(energy)
550  class(condition), intent(in) :: this
551  !> @return Return the agent's maximum energy reserves.
552  real(srp) :: energy
553 
554  energy = this%energy_maximum
555 
556  end function condition_energy_maximum_get
557 
558  !-----------------------------------------------------------------------------
559  !> Get current body length. *Standard GET-function.*
560  elemental function condition_body_length_get(this) result(length)
561  class(condition), intent(in) :: this
562  !> @return Return the agent's body length.
563  real(srp) :: length
564 
565  length = this%body_length
566 
567  end function condition_body_length_get
568 
569  !-----------------------------------------------------------------------------
570  !> Get current value of the control unselected trait. Standard GET-function.
571  elemental function condition_control_unsel_get(this) result(value_out)
572  class(condition), intent(in) :: this
573  !> @return Return the agent's control unselected trait value.
574  real(srp) :: value_out
575 
576  value_out = this%control_unselected
577 
578  end function condition_control_unsel_get
579 
580  !-----------------------------------------------------------------------------
581  !> Get current body mass. *Standard GET-function.*
582  elemental function condition_body_mass_get(this) result(mass)
583  class(condition), intent(in) :: this
584  !> @return Return the agent's body mass.
585  real(srp) :: mass
586 
587  mass = this%body_mass
588 
589  end function condition_body_mass_get
590 
591  !-----------------------------------------------------------------------------
592  !> Calculate the visibility range of this agent. Visibility depends on the
593  !! size of the agent, ambient illumination and agent contrast. Visibility is
594  !! the distance from which this agent can be seen by a visual object (e.g.
595  !! predator or conspecific). This function is a wrapper to the
596  !! the_environment::visual_range() function.
597  !! @warning The `visual_range` procedures use meter for units, this
598  !! auto-converts to cm.
599  !! @warning Cannot implement a generic function accepting also vectors of
600  !! this objects as only elemental object-bound array functions are
601  !! allowed by the standard. This function cannot be elemental, so
602  !! passed-object dummy argument must always be scalar.
603  function condition_agent_visibility_visual_range(this, object_area, &
604  contrast, time_step_model) result (visrange)
605  class(condition), intent(in) :: this
606  !> @param[in] object_area optional area of this agent, m. If not provided
607  !! (normally), is obtained from the body length attribute of
608  !! the agent (the_body::condition::body_length).
609  real(srp), optional, intent(in) :: object_area
610  !> @param[in] contrast is the inherent visual contrast of the agent.
611  !! the default contrast of all objects is defined by the
612  !! commondata::preycontrast_default parameter.
613  real(srp), optional, intent(in) :: contrast
614  !> @param[in] optional time step of the model, if absent gets the current
615  !! time step as defined by the value of
616  !! `commondata::global_time_step_model_current`.
617  integer, optional, intent(in) :: time_step_model
618  !> @return The maximum distance from which this agent can be seen.
619  real(srp) :: visrange
620 
621  ! Local copies of optionals
622  real(srp) :: object_area_here, contrast_here
623  integer :: time_step_model_here
624 
625  ! Local variables
626  real(srp) :: irradiance_agent_depth
627 
628  !> ### Implementation details ###
629  !> **Checks.** Check optional object area, the default value, if this
630  !> parameter is absent, the body side area is calculated from the
631  !! the_body::condition::body_length attribute of the agent with inline
632  !! conversion to m. Note that the body side area of a fish object is
633  !! calculated from the body length using the
634  !! commondata::length2sidearea_fish() function.
635  if (present(object_area)) then
636  object_area_here = object_area
637  else
638  object_area_here = length2sidearea_fish( cm2m( this%body_length ) )
639  end if
640 
641  !> Check optional `contrast` parameter. If unset, use global
642  !! `commondata::preycontrast_default`.
643  if (present(contrast)) then
644  contrast_here = contrast
645  else
646  contrast_here = preycontrast_default
647  end if
648 
649  !> Check optional time step parameter. If unset, use global
650  !! `commondata::global_time_step_model_current`.
651  if (present(time_step_model)) then
652  time_step_model_here = time_step_model
653  else
654  time_step_model_here = global_time_step_model_current
655  end if
656 
657  !> Calculate ambient illumination / irradiance at the depth of
658  !! this agent at the given time step using the
659  !! the_environment::spatial::illumination() method.
660  irradiance_agent_depth = this%illumination(time_step_model_here)
661 
662  !> Return visual range to see this spatial object: its visibility range by
663  !! calling the the_environment::visual_range() function.
664  visrange = m2cm( visual_range( irradiance = irradiance_agent_depth, &
665  prey_area = object_area_here, &
666  prey_contrast = contrast_here ) )
667 
669 
670  !-----------------------------------------------------------------------------
671  !> Set body mass optionally updating the history stack.
672  subroutine condition_body_mass_set_update_hist(this, value_set, &
673  update_history)
674  class(condition), intent(inout) :: this
675  !> @param value_set, Set the new (overwrite) value of the **body mass**.
676  real(SRP), intent(in) :: value_set
677  !> @param update_history is an optional logical flag to update the body
678  !! mass history stack, the default is **not to update**.
679  logical, optional, intent(in) :: update_history
680 
681  !> ### Implementation details ###
682  !> If the `value_set` is smaller that the minimum body mass parameter
683  !! `BODY_MASS_MIN`, the body mass is set to this minimum value. This avoids
684  !! getting the body mass too small or negative.
685  !> This "set"-procedure, however, does not check if the new value is below
686  !! the structure mass or any other minimum value that leads to the death of
687  !! the agent. To check for starvation death, the method
688  !! `condition::starved_death()` =>
689  !! `the_body::body_mass_is_starvation_check()` should be explicitly
690  !! executed.
691  if ( value_set < body_mass_min ) then
692  this%body_mass = body_mass_min
693  else
694  this%body_mass = value_set
695  end if
696 
697  !> Update the body mass history stack if the `update_history` is
698  !! explicitly set to TRUE. The default not to update is used because
699  !! body mass should normally be updated in parallel with the length, if
700  !! this is not the case, they will be dis-synchronised within the
701  !! history stack arrays.
702  if (present(update_history)) then
703  if (update_history) &
704  call add_to_history(this%body_mass_history, value_set)
705  end if
706 
708 
709  !-----------------------------------------------------------------------------
710  !> Set body length optionally updating the history stack.
711  subroutine condition_body_length_set_update_hist(this, value_set, &
712  update_history)
713  class(condition), intent(inout) :: this
714  !> @param value_set, Set the new (overwrite) value of the **body length**.
715  real(SRP), intent(in) :: value_set
716  !> @param update_history is an optional logical flag to update the body
717  !! length history stack, the default is **not to update**.
718  logical, optional, intent(in) :: update_history
719 
720  !> ### Implementation details ###
721  !> If the `value_set` is smaller that the minimum body length parameter
722  !! `BODY_LENGTH_MIN` or the maximum `BODY_LENGTH_MAX`, the length is set
723  !! to this minimum or maximum value respectively. This avoids setting
724  !! the body length outside of the normal limits. The function
725  !! `commondata::within()` is called to set the new value.
726  this%body_length = within(value_set, body_length_min, body_length_max)
727 
728  !> Update the body length history stack if the `update_history` is
729  !! explicitly set to TRUE. The default not to update is used because
730  !! body length should normally be updated in parallel with the mass, if
731  !! this is not the case, they will be dis-synchronised within the
732  !! history stack arrays.
733  if (present(update_history)) then
734  if (update_history) &
735  call add_to_history(this%body_length_history, value_set)
736  end if
737 
739 
740  !-----------------------------------------------------------------------------
741  !> Get historical record of energy reserves at birth. *Standard GET-function.*
742  elemental function condition_energy_birth_get(this) result(energy)
743  class(condition), intent(in) :: this
744  !> @return Return the agent's body length at birth.
745  real(srp) :: energy
746 
747  energy = this%energy_birth
748 
749  end function condition_energy_birth_get
750 
751  !-----------------------------------------------------------------------------
752  !> Get historical record of body length at birth. *Standard GET-function.*
753  elemental function condition_body_length_birth_get(this) result(length)
754  class(condition), intent(in) :: this
755  !> @return Return the agent's body length at birth.
756  real(srp) :: length
757 
758  length = this%body_length_birth
759 
761 
762  !-----------------------------------------------------------------------------
763  !> Get historical record of body mass at birth. *Standard GET-function.*
764  elemental function condition_body_mass_birth_get(this) result(mass)
765  class(condition), intent(in) :: this
766  !> @return Return the agent's body mass at birth.
767  real(srp) :: mass
768 
769  mass = this%body_mass_birth
770 
771  end function condition_body_mass_birth_get
772 
773  !-----------------------------------------------------------------------------
774  !> Get historcal maximum for body mass. Standard *GET-function.*
775  elemental function condition_body_mass_max_get(this) result(mass)
776  class(condition), intent(in) :: this
777  !> @return Return the agent's maximum body mass.
778  real(srp) :: mass
779 
780  mass = this%body_mass_maximum
781 
782  end function condition_body_mass_max_get
783 
784  !-----------------------------------------------------------------------------
785  !> Get current smr. Standard *GET-function.*
786  elemental function condition_smr_get(this) result(smr)
787  class(condition), intent(in) :: this
788  !> @return Return the agent's SMR.
789  real(srp) :: smr
790 
791  smr = this%smr
792 
793  end function condition_smr_get
794 
795  !-----------------------------------------------------------------------------
796  !> Get current stomach content. *Standard GET-function.*
797  elemental function condition_stomach_content_get(this) result(stom)
798  class(condition), intent(in) :: this
799  !> @return Return the agent's stomach content.
800  real(srp) :: stom
801 
802  stom = this%stomach_content_mass
803 
804  end function condition_stomach_content_get
805 
806  !=============================================================================
807 
808  !> @brief Calculate the basic processing cost of catching a food item
809  !! with the mass `food_gain`.
810  !! @details There is a small cost of the food item catching, in terms of the
811  !! **food item mass** (proportional cost). So, if the agent does
812  !! an unsuccessful attempt to catch a food item, the cost still
813  !! applies. So we subtract it before testing if the agent actually
814  !! got this food item. Also, there is a fixed minimum capture cost
815  !! (in terms of the **agent body mass**), so if the food item is
816  !! very small, the actual gain can be negative (capture cost exceeds
817  !! the value of the item).
818  !! @note Note that this version accepts the the raw food mass (real value).
819  elemental function body_mass_processing_cost_calc_v(this, &
820  food_gain, distance_food) &
821  result(cost)
822  class(condition), intent(in) :: this !> @param[in] this object.
823  real(srp), optional, intent(in) :: food_gain !> @param[in] food gain.
824  !> @param[in] distance_food distance to the food item.
825  real(srp), optional, intent(in) :: distance_food
826  reaL(srp) :: cost !> @return processing cost.
827 
828  ! Local copy of optionals.
829  real(srp) :: food_gain_here, distance_food_here
830 
831  ! Check optional parameter, set default values.
832  if(present(food_gain)) then
833  food_gain_here = food_gain
834  else
835  food_gain_here = food_item_size_default
836  end if
837 
838  !> ### Implementation details ###
839  !> First, check the optional distance towards the food item. It is used to
840  !! calculate the energetic cost of swimming towards the food item.
841  if (present(distance_food)) then
842  distance_food_here = distance_food
843  else
844  !> If the distance to the food item is not provided, we assume it is
845  !! equal to the *agent size* (so the relative distance = 1 body size).
846  distance_food_here = this%body_length
847  end if
848 
849  !> The cost of the processing of the food item is a sum of two components:
850  !! 1. some small processing cost depending on the food item mass and
851  !! 2. the cost of swimming towards the food item depending on the relative
852  !! distance (distance in terms of the agent body length.
853  !! .
854  !! @f[ C_{p} = max(\mu \cdot \beta_{fp}, \mu \cdot C_{smr}) + C_{s} , @f]
855  !! where @f$ \mu @f$ is the food gain, @f$ \beta_{fp} @f$ is a factor
856  !! proportional to the food item mass, and @f$ C_{smr} @f$ is a food
857  !! processing cost factor that is proportional to the agent's SMR.
858  cost = max( food_gain_here * food_item_capture_prop_cost, &
859  food_gain_here * this%cost_factor_food_smr(food_gain_here) ) &
860  + this%cost_swim(distance=distance_food_here)
861 
863 
864  !-----------------------------------------------------------------------------
865  !> The cost of swimming of a specific distance in terms of the actor's
866  !! body mass.
867  !! @note Note that power needed to swim is proportional to the body
868  !! mass with the exponent 0.6 assuming turbulent flow (see
869  !! doi:10.1242/jeb.01484).
870  !! @param[in] distance the optional distance traversed (absolute distance
871  !! in real units, cm). If distance is not provided, it is
872  !! calculated from the latest spatial displacement of the agent
873  !! using the the_environment::spatial_moving::way() function.
874  !! @param[in] exponent an optional cost exponent parameter. Can be 0.5
875  !! (commondata::swimming_cost_exponent_laminar, laminar flow) or
876  !! 0.6 (commondata::swimming_cost_exponent_turbulent, turbulent
877  !! flow), the default is set to 0.6.
878  !! @returns The cost of swimming in terms of the body mass lost.
879  elemental function condition_cost_swimming_burst(this, &
880  distance, exponent) result (cost_swimming)
881  class(condition), intent(in) :: this ! This object.
882  real(srp), optional, intent(in) :: distance ! Distance traversed.
883  real(srp), optional, intent(in) :: exponent ! Cost exponent.
884  real(srp) :: cost_swimming ! Return value.
885 
886  ! Local copies of optionals.
887  real(srp) :: dist_loc, exponent_here
888 
889  !> ### Notable parameters ###
890  !! **SWIM_COST_EXP** is the default swimming cost body mass exponent
891  !! parameter for turbulent flow
892  !! commondata::swimming_cost_exponent_turbulent = 0.6. For laminar flow,
893  !! equal to commondata::swimming_cost_exponent_laminar = 0.5.
894  !! See doi:10.1242/jeb.01484 (https://dx.doi.org/10.1242/jeb.01484).
895  real(srp), parameter :: swim_cost_exp = swimming_cost_exponent_turbulent
896 
897  ! Check optional distance
898  if (present(distance)) then
899  dist_loc = distance
900  else
901  dist_loc = this%way()
902  end if
903 
904  ! Check optional exponent parameter.
905  if (present(exponent)) then
906  exponent_here = exponent
907  else
908  exponent_here = swim_cost_exp
909  end if
910 
911  !> ### Implementation details ###
912  !> The cost of swimming (for turbulent flow) is calculated as:
913  !! @f[ C_{s} = M^{0.6} \cdot \beta \cdot d / L , @f] where
914  !! @f$ M @f$ is the body mass, @f$ \beta @f$ is a parameter factor
915  !! defined as `commondata::swimming_speed_cost_burst`, @f$ d / L @f$ is
916  !! the distance in units of the agent's body length. For laminar flow,
917  !! the exponent should be 0.5.
918  !! @note An arbitrary value for the exponent can be provided as the second
919  !! dummy parameter to this function `exponent`.
920  !! @note The function the_body::cost_swimming_standard() calculates a
921  !! diagnostic function, the "standard" cost of swimming.
922  cost_swimming = this%body_mass**exponent_here * swimming_speed_cost_burst &
923  * dist_loc / this%body_length
924 
925  end function condition_cost_swimming_burst
926 
927  !-----------------------------------------------------------------------------
928  !> @brief Calculate the basic processing cost of catching a food item
929  !! with the mass `food_gain`.
930  !! @note Note that this version accepts the food object not its raw mass.
931  !! @param[in] food_obj food item object, of class `FOOD_ITEM`.
932  !! @param[in] distance_food distance to the food item.
933  !! @return Food processing cost.
934  elemental function body_mass_processing_cost_calc_o(this, &
935  food_obj, distance_food) &
936  result(cost)
937  class(condition), intent(in) :: this ! @param[in] this object.
938  class(food_item), intent(in) :: food_obj ! @param[in] food item object.
939  ! @param[in] distance_food distance to the food item.
940  real(srp), optional, intent(in) :: distance_food
941  reaL(srp) :: cost ! @returns processing cost.
942 
943  ! Local copy of optionals.
944  real(srp) :: distance_food_here
945 
946  !> ### Implementation details ###
947  ! The swimming cost body mass exponent parameter for turbulent flow is
948  ! equal to 0.6 (see doi:10.1242/jeb.01484).
949  ! @note **Disabled** here as this procedure now uses the above scalar
950  ! `food_proc_cost_v` function for calculations.
951  !real(SRP), parameter :: SWIM_COST_EXP = 0.6_SRP
952 
953  !> First, check the optional distance towards the food item. We use it to
954  !! calculate the energetic cost of swimming towards the food item.
955  if (present(distance_food)) then
956  distance_food_here = distance_food
957  else
958  !> If the distance to the food item is not provided, we assume it is
959  !! equal to the agent body size (so the relative distance = 1 body size).
960  distance_food_here = this%body_length
961  end if
962 
963  !> The cost of the processing of the food item is a sum of two components:
964  !! 1. some small processing cost depending on the food item mass and
965  !! 2. the cost of swimming towards the food item depending on the relative
966  !! distance (distance in terms of the agent body length.
967  !! .
968  !! @f[ C_{p} = max(\mu \cdot \beta_{fp}, \mu \cdot C_{smr}) + C_{s} , @f]
969  !! where @f$ \mu @f$ is the food gain, @f$ \beta_{fp} @f$ is a factor
970  !! proportional to the food item mass, and @f$ C_{smr} @f$ is a food
971  !! processing cost factor that is proportional to the agent's SMR.
972  !!
973  !! @note The calculations are done by the scalar procedure
974  !! body_mass_processing_cost_calc_v().
975  cost = this%food_proc_cost_v(food_obj%get_mass(), distance_food_here)
976 
978 
979  !-----------------------------------------------------------------------------
980  !> Calculate the value of possible food gain as fitting into the agent's
981  !! stomach, or the full gain if the food item wholly fits in.
982  !! @param[in] food_gain food gain.
983  !! @param[in] food_dist distance to food.
984  !! @returns processing cost.
985  !! @note Note that this version accepts the the raw food mass (real value).
986  !! @note The food fitting is adjusted for the food item processing cost
987  !! body_mass_processing_cost_calc_v() call.
988  elemental function stomach_content_food_gain_fitting_v(this, &
989  food_gain, food_dist) &
990  result(food_adjusted)
991  class(condition), intent(in) :: this
992  real(srp), optional, intent(in) :: food_gain ! @param[in] food gain.
993  real(srp), optional, intent(in) :: food_dist ! @param[in] distance to food.
994  reaL(srp) :: food_adjusted ! @returns processing cost.
995 
996  real(srp) :: food_gain_here
997 
998  !> ### Implementation details ###
999  !> Check optional `food_gain` parameter, set default values. If food
1000  !! gain is not provided, an average/default food item is assumed, defined
1001  !! by `FOOD_ITEM_SIZE_DEFAULT`.
1002  if(present(food_gain)) then
1003  food_gain_here = food_gain
1004  else
1005  food_gain_here = food_item_size_default
1006  end if
1007 
1008  if (present(food_dist)) then
1009  food_adjusted = food_gain_here - this%food_surplus(food_gain_here) - &
1010  this%food_process_cost(food_gain_here, food_dist)
1011  else
1012  food_adjusted = food_gain_here - this%food_surplus(food_gain_here) - &
1013  this%food_process_cost(food_gain_here)
1014  end if
1015 
1017 
1018  !-----------------------------------------------------------------------------
1019  !> Calculate the value of possible food gain as fitting into the agent's
1020  !! stomach (or full gain if the food item fits wholly).
1021  !! @note Note that this version accepts the food object not its raw mass.
1022  !! @note Note that the food fitting is adjusted for the food item
1023  !! processing cost via `food_process_cost` call.
1024  elemental function stomach_content_food_gain_fitting_o(this, &
1025  food_obj, food_dist) &
1026  result(food_adjusted)
1027  class(condition), intent(in) :: this !> @param[in] this object.
1028  class(food_item), intent(in) :: food_obj !> @param[in] food gain.
1029  real(srp), optional, intent(in) :: food_dist !> @param[in] distance to food.
1030  real(srp) :: food_adjusted !> @returns processing cost.
1031 
1032  !> This code is **not using** the `food_fitt_v` scalar-based function
1033  !! above:
1034  !! `if (present(food_dist)) then
1035  !! food_adjusted = food_obj%get_mass() - this%food_surplus(food_obj) - &
1036  !! this%food_process_cost(food_obj, food_dist)
1037  !! else
1038  !! food_adjusted = food_obj%get_mass() - this%food_surplus(food_obj) - &
1039  !! this%food_process_cost(food_obj)
1040  !! end if`
1041 
1042  !> This code **uses** the `food_fitt_v` scalar-based function above
1043  !! to avoid code duplication.
1044  if (present(food_dist)) then
1045  food_adjusted = this%food_fitt_v(food_obj%get_mass(), food_dist)
1046  else
1047  food_adjusted = this%food_fitt_v(food_obj%get_mass())
1048  end if
1049 
1051 
1052  !-----------------------------------------------------------------------------
1053  !> Calculate extra food surplus mass non fitting into the stomach of the
1054  !! agent.
1055  !! @note Note that this version accepts the the raw food mass (real value).
1056  elemental function stomach_content_food_gain_non_fit_v(this, food_gain) &
1057  result(extra_food)
1058  class(condition), intent(in) :: this !> @param[in] this object self.
1059  real(srp), optional, intent(in) :: food_gain !> @param[in] food gain.
1060  reaL(srp) :: extra_food !> @returns food surplus.
1061 
1062  !> Maximum stomach capacity is determined by the factor `maxstomcap` in
1063  !! proportion of the body mass. The stomach content cannot surpass
1064  !! `maxstomcap`=15% of agent's body mass.
1065  real(srp) :: stomach_content_ceiling
1066 
1067  real(srp) :: food_gain_here
1068 
1069  !> Check optional parameter, set default values.
1070  if(present(food_gain)) then
1071  food_gain_here = food_gain
1072  else
1073  food_gain_here = food_item_size_default
1074  end if
1075 
1076  stomach_content_ceiling = this%body_mass * this%maxstomcap
1077 
1078  !> Get the possible food surplus, the part of the food gain that does
1079  !! not fit into the agent's stomach. If happily fits, takes zero.
1080  extra_food = max(0.0_srp, this%stomach_content_mass + food_gain_here - &
1081  stomach_content_ceiling)
1082 
1084 
1085  !-----------------------------------------------------------------------------
1086  !> Calculate extra food surplus mass non fitting into the stomach of the
1087  !! agent.
1088  !! @note Note that this version accepts the food object not its raw mass.
1089  elemental function stomach_content_food_gain_non_fit_o(this, food_obj) &
1090  result(extra_food)
1091  class(condition), intent(in) :: this !> @param[in] this object self.
1092  class(food_item), intent(in) :: food_obj !> @param[in] food gain.
1093  reaL(srp) :: extra_food !> @returns food surplus.
1094 
1095  !> Maximum stomach capacity is determined by the factor `maxstomcap` in
1096  !! proportion of the body mass. The stomach content cannot surpass
1097  !! `maxstomcap`=15% of agent's body mass.
1098  real(srp) :: stomach_content_ceiling
1099 
1100  stomach_content_ceiling = this%body_mass * this%maxstomcap
1101 
1102  !> Get the possible food surplus, the part of the food gain that does
1103  !! not fit into the agent's stomach. If happily fits, takes zero.
1104  extra_food = max(0.0_srp, this%stomach_content_mass + &
1105  food_obj%get_mass() - stomach_content_ceiling)
1106 
1108 
1109 
1110 
1111 
1112 
1113 
1114 
1115 
1116 
1117 
1118 
1119 
1120 
1121  !-----------------------------------------------------------------------------
1122  !> Calculate the cost of living for a single model step.
1123  !! So the agent mass increment per a single model step should subtract this
1124  !! cost.
1125  !! @note Should be calculated at the end of model time step.
1126  elemental function body_mass_calculate_cost_living_step(this) result(stepcost)
1127  class(condition), intent(in) :: this
1128  real(srp) :: stepcost !> energetic cost of bodymass growth per time step.
1129 
1130  ! Check erroneous value of body mass, this results in a
1131  ! commondata::missing standard cost.
1132  if (this%body_mass < zero) then
1133  stepcost = missing
1134  return
1135  end if
1136 
1137  !> The energetic costs is a fraction of body weight and scales to
1138  !! number of time steps : @f[ M_{c}= \frac{C B}{\Omega} @f] (eq. 1)
1139  stepcost = this%body_mass * living_cost / lifespan
1140 
1142 
1143  !-----------------------------------------------------------------------------
1144  !> Adjust the body mass at the end of the model step against the cost of
1145  !! living. We do not adjust the cost of living at each food gain as several
1146  !! food items can be consumed by the agent at a single time step of the model.
1147  !! Cost of living is now calculated at the end of the time step of the model.
1148  !! @note Should be calculated at the end of model time step.
1149  elemental subroutine body_mass_adjust_living_cost_step(this)
1150  class(condition), intent(inout) :: this
1151 
1152  this%body_mass = this%body_mass - this%living_cost()
1153 
1154  end subroutine body_mass_adjust_living_cost_step
1155 
1156  !-----------------------------------------------------------------------------
1157  !> Do grow body mass based on food gain from a single food item adjusted
1158  !! for cost etc.
1159  !! @note Can be calculated after consumption of each food item, many times
1160  !! within a single time step of the model.
1161  elemental subroutine body_mass_grow_do_calculate(this, food_gain, update_history)
1162  class(condition), intent(inout) :: this !> @param[inout] self.
1163  real(srp), intent(in) :: food_gain !> @param[in] food gain.
1164  !> @param[in] update_history optional logical flag to enable saving
1165  !! the body mass value to the body mass history stack.
1166  !! @warning History update is disabled by default because the length and
1167  !! mass histories can be updated separately, so could get not
1168  !! synchronous.
1169  logical, optional, intent(in) :: update_history
1170 
1171  !> Add the food increment to the current body mass.
1172  this%body_mass = max( this%body_mass + food_gain , body_mass_min )
1173 
1174  !> And also update the historical maximum value, if the current exceeds.
1175  if (this%body_mass > this%body_mass_maximum) &
1176  this%body_mass_maximum = this%body_mass
1177 
1178  !> Add the current updated body mass to the history stack.
1179  if (present(update_history)) then
1180  if (update_history) &
1181  call add_to_history(this%body_mass_history, this%body_mass)
1182  end if
1183 
1184  end subroutine body_mass_grow_do_calculate
1185 
1186  !-----------------------------------------------------------------------------
1187  !> The fraction of the cost of the processing of the food item(s) depending
1188  !! on the agent SMR. It is scaled in terms of the ratio of the food item mass
1189  !! to the agent mass.
1190  elemental function body_mass_food_processing_cost_factor_smr(this,food_gain) &
1191  result(cost_factor)
1192  class(condition), intent(in) :: this !> @param[inout] self.
1193  real(srp), intent(in) :: food_gain !> @param[in] food gain.
1194  real(srp) :: cost_factor
1195 
1196  cost_factor = max( food_gain / this%body_mass * cost_factor_foraging_smr &
1197  * this%smr, 0.0_srp )
1198 
1200 
1201  !-----------------------------------------------------------------------------
1202  !> Do increment stomach contents with adjusted (fitted) value.
1203  !! @note Note that the `stomach_increment` should be adjusted
1204  !! for fitting size. This is the actual increment.
1205  elemental subroutine stomach_content_get_increment(this, stomach_increment)
1206  class(condition), intent(inout) :: this
1207  real(srp), intent(in) :: stomach_increment
1208 
1209  !> ### Implementation details ###
1210  !> Stomach content mass is incremented by the `stomach_increment` value.
1211  ! Negative stomach increment is not processed as we cannot have negative
1212  ! stomach content mass.
1213  if (stomach_increment > 0.0_srp) this%stomach_content_mass = &
1214  this%stomach_content_mass + stomach_increment
1215 
1216  end subroutine stomach_content_get_increment
1217 
1218  !-----------------------------------------------------------------------------
1219  !> @brief Calculate body length increment for a time step of the model.
1220  !! @details This function describes linear growth of the agent resulting from
1221  !! food intake. Linear growth increment scales with **growth
1222  !! hormone** level. The increment in length is weighted by the growth
1223  !! hormone factor that is obtained via interpolation. So, if the
1224  !! agent's growth hormone level is very low, the growth increment
1225  !! factor is near-zero, if growth hormone level is high, the growth
1226  !! increment approaches the maximum value that is proportional to the
1227  !! body mass increment in units of the agent's body mass (growth
1228  !! hormone weighting factor approaches 1.0).
1229  function body_len_grow_calculate_increment_step(this, mass_increment) &
1230  result(length_increment)
1231  class(condition), intent(in) :: this
1232  real(srp), intent(in) :: mass_increment !> @param increment of the weight
1233 
1234  real(srp) :: length_increment !> @returns Body length increment
1235 
1236  !> ### Notable local parameters ###
1237  !> `increment_factor_ipoint` is a local parameter showing the linear
1238  !! growth increment factor interpolation point, @f$ \vartheta @f$ in the
1239  !! formula below.
1240  real(srp) :: increment_factor_ipoint
1241 
1242  !> ### Implementation details ###
1243  !> If the body mass increment is positive and exceeds fixed threshold
1244  !! `MASS_GROWTH_THRESHOLD`, the agent can grow body length. Otherwise,
1245  !! if the mass threshold is not exceeded in MASS_THRESHOLD, the agent
1246  !! does not increase in length. This check is done in the main named
1247  !! if condition block `MASS_THRESHOLD`.
1248  !> #### MASS_THRESHOLD block ####
1249  mass_threshold: if (mass_increment > &
1250  this%body_mass * mass_growth_threshold) then
1251 
1252  !> - **First,** we get the interpolation-based growth increment factor
1253  !! `increment_factor_ipoint` (@f$ \vartheta @f$) depending on the
1254  !! agent's current **growth hormone** level. The function linking
1255  !! growth hormone level and the linear growth increment factor
1256  !! (@f$ \vartheta @f$) is represented by this relationship:
1257  !! @image html img_doxygen_growth_linear_factor.svg
1258  !! @image latex img_doxygen_growth_linear_factor.eps "Linear growth increment factor" width=14cm
1259  !! @note Note that the linear interpolation `LINTERPOL` engine is used
1260  !! here instead of non-linear `DDPINTERPOL`. This is done because
1261  !! of not well predictable raw values in the grid abscissa;
1262  !! `DDPINTERPOL` tends to produce sigmoidal waves here and needs
1263  !! precise tuning of the interpolation grid parameter arrays
1264  !! - `LINEAR_GROWTH_HORMONE_INCREMENT_FACTOR_CURVE_ABSCISSA`
1265  !! - `LINEAR_GROWTH_HORMONE_INCREMENT_FACTOR_CURVE_ORDINATE`.
1266  !! .
1267  increment_factor_ipoint = linterpol( &
1270  this%growhorm_get() )
1271 
1272  !> - Save the interpolation plot in the @ref intro_debug_mode
1273  !! "debug mode" using external command.
1274  !! @warning Involves **huge** number of plots, should normally be
1275  !! disabled.
1279  ipol_value=this%growhorm_get(), algstr="LINTERPOL", &
1280  output_file="plot_debug_growth_linear_factor_" // &
1281  tostr(global_time_step_model_current) // &
1282  mmdd // "_a_"// trim(this%individ_label()) // "_" // &
1283  rand_string(label_length, label_cst,label_cen) // ps )
1284 
1285  !> - **Second,** The body length increment in units of length
1286  !! @f$ \frac{\Delta L}{L} @f$ is proportional to the body mass
1287  !! increment in units of mass: @f$ \frac{\Delta M}{M} @f$, however
1288  !! weighted by the linear growth increment factor @f$ \vartheta @f$
1289  !! that depends on the growth hormone and is obtained via interpolation
1290  !! (see above). If the agent's growth hormone level is very low, the
1291  !! growth increment factor is near-zero and linear growth increment is
1292  !! also near-zero. However, if growth hormone level is high, the growth
1293  !! increment weighting factor @f$ \vartheta @f$ approaches the maximum
1294  !! value that is proportional to the body mass increment in units of
1295  !! the agent's body mass:
1296  !! @f[ \Delta L = L \cdot \vartheta \cdot \frac{\Delta M}{M} , @f]
1297  !! where @f$ \Delta L @f$ is the body length increment, @f$ L @f$ is
1298  !! the body length, @f$ \vartheta @f$ is the growth-hormone-dependent
1299  !! linear growth increment factor, @f$ \frac{\Delta M}{M} @f$ is the
1300  !! body mass increment in units of body mass. So the relative body
1301  !! length increment is proportional to the relative body mass increment.
1302  length_increment = this%body_length * increment_factor_ipoint * &
1303  mass_increment / this%body_mass
1304 
1305  else mass_threshold
1306 
1307  !> - If the mass threshold is not exceeded in MASS_THRESHOLD, the agent
1308  !! does not increase in length, the length increment is zero.
1309  !!
1310  length_increment = 0.0_srp
1311 
1312  end if mass_threshold
1313 
1315 
1316  !-----------------------------------------------------------------------------
1317  !> Do linear growth for one model step based on the increment function
1318  !! the_body::condition::len_incr().
1319  !! @note Should be calculated at the end of model time step.
1320  subroutine body_len_grow_do_calculate_step(this, mass_increment, update_history)
1321  class(condition), intent(inout) :: this !> @param[inout] self
1322  real(SRP), intent(in) :: mass_increment !> @param increment of the weight
1323  !> @param[in] update_history optional logical flag to enable saving
1324  !! the body mass value to the body mass history stack.
1325  !! @warning History update is disabled by default because the length and
1326  !! mass histories can be updated separately, so could get not
1327  !! synchronous.
1328  logical, optional, intent(in) :: update_history
1329 
1330  !> ### Implementation details ###
1331  !> Body length is incremented by a value of the
1332  !! the_body::condition::len_incr() function.
1333  this%body_length = this%body_length + this%len_incr(mass_increment)
1334 
1335  !> Also, the current updated body length is added to the history stack.
1336  if (present(update_history)) then
1337  if (update_history) &
1338  call add_to_history(this%body_length_history, this%body_length)
1339  end if
1340 
1341  end subroutine body_len_grow_do_calculate_step
1342 
1343  !-----------------------------------------------------------------------------
1344  !> @brief Update the level of the sex steroids.
1345  !! @details Sex steroids are incremented each model time step. Testosteron is
1346  !! incremented in males and estrogen, in females. However, such an
1347  !! increment occurs only if there has recently been any body length
1348  !! growth (which occurs only if the food gain exceeds a specific
1349  !! threshold value). The growth increment is calculated as the
1350  !! difference between the current body length and the maximum body
1351  !! length in `n` latest historical entries from the length history
1352  !! stack. The `n` value is set by the parameter
1353  !! commondata::sex_steroids_check_history.
1355  class(condition), intent(inout) :: this
1356 
1357  ! Local variables.
1358  real(SRP) :: length_increment, steroid_increment_factor
1359 
1360  !> ### Implementation details ###
1361  !> First, the sex steroid **increment factor** is calculated using
1362  !! a nonparametric relationship. Calculations can be based either
1363  !! on its link with the **age** or the **body length**:
1364  !! - ::steroid_factor_age() or
1365  !! - ::steroid_factor_len().
1366  !! .
1367  !! These are the two alternative procedures implemented here.
1368  !! @note Here implementation is based on ::steroid_factor_age().
1369  steroid_increment_factor = steroid_factor_age()
1370 
1371  !> Next, calculate the **past increments of the body length** across the
1372  !! body length history stack. If there has been any increment in the body
1373  !! length during the commondata::sex_steroids_check_history latest steps
1374  !! in the history stack **and** the current length, sex steroids are
1375  !! incremented. If such an increment is zero, sex steroids are not
1376  !> incremented. The length increment over the latest history is calculated
1377  !! as follows:
1378  !! @code
1379  !! length_increment = &
1380  !! maxval( [history_array, current_value] ) - &
1381  !! minval( [history_array, current_value] )
1382  !! @endcode
1383  length_increment = &
1384  maxval( [this%body_length_history( &
1386  history_size_agent_prop), this%body_length], &
1387  [this%body_length_history( &
1389  history_size_agent_prop), this%body_length] /= missing &
1390  ) - & ! @note minus sign here
1391  minval( [this%body_length_history( &
1393  history_size_agent_prop), this%body_length], &
1394  [this%body_length_history( &
1396  history_size_agent_prop), this%body_length] /= missing &
1397  )
1398  ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1399  ! Previous implementation:
1400  ! @note Note that only non-MISSING values count: `maxval`
1401  ! uses a **mask**.
1402  ! @note **This version** checks the current body length against the
1403  ! maximum historical value. It is disabled now.
1404  !length_increment = this%body_length - &
1405  ! maxval( this%body_length_history( &
1406  ! HISTORY_SIZE_AGENT_PROP-SEX_STEROIDS_CHECK_HISTORY+1: &
1407  ! HISTORY_SIZE_AGENT_PROP), &
1408  ! this%body_length_history( &
1409  ! HISTORY_SIZE_AGENT_PROP-SEX_STEROIDS_CHECK_HISTORY+1: &
1410  ! HISTORY_SIZE_AGENT_PROP) /= MISSING &
1411  ! )
1412  ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1413 
1414  !> Finally, do increment the sex steroids depending on the body length
1415  !! (`length_increment`) value. Sex steroids get non-zero increment only
1416  !! if there has been some growth of the body length
1417  !! (`length_increment>0.0`). Otherwise a previous value is retained.
1418  ! TODO: replace if condition to the start of the procedure with return
1419  ! to save on steroid_increment_factor dry calculation overhead.
1420  if (length_increment > tolerance_low_def_srp) then
1421  if (this%is_male()) then
1422  !> - If the agent is **male**, **testosterone** is incremented.
1423  call this%testosterone_set( min( 10.0_srp, &
1424  this%testosterone_get() + &
1425  this%testosterone_get() * steroid_increment_factor ) )
1426  else
1427  !> - If the agent is **female**, **estrogen** is incremented.
1428  !! .
1429  call this%estrogen_set( min( 10.0_srp, &
1430  this%estrogen_get() + &
1431  this%estrogen_get() * steroid_increment_factor ) )
1432  end if
1433  !> If there was no growth and the gonadal steroids are not incremented,
1434  !! the current values are still saved in the history stack by calling
1435  !! the_hormones::hormones::hormones_to_history().
1436  else
1437  call this%hormones_to_history()
1438  end if
1439 
1440  contains
1441  !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1442  !> Function calculating the value of the sex steroid increment factor that
1443  !! depends on the agent's **age**.
1444  !! Calculate the steroid increment factor. It is set as a nonparametric
1445  !! relationship that is set by a linear interpolation LINTERPOL (or
1446  !! DDPINTERPOL) of a parameter grid values. The increment of the sex
1447  !! steroid hormones depends on the **age** of the agent: it is very slight
1448  !! at the early stage of the ontogeny, i.e. small age, but increase to the
1449  !! end of the agent's lifespan.
1450  function steroid_factor_age() result (value_out)
1451  real(srp) :: value_out
1452 
1453  !> Calculate the steroid increment factor. It is set as a nonparametric
1454  !! relationship that is set by a linear interpolation LINTERPOL (or
1455  !! DDPINTERPOL) of a parameter grid values. The increment of the sex
1456  !! steroid hormones depends on the **age** of the agent: it is very slight
1457  !! at the early stage of the ontogeny, i.e. small age, but increase to the
1458  !! end of the agent's lifespan.
1459  value_out = ddpinterpol(sex_steroids_increment_factor_age_curve_abscissa, &
1461  real(this%get_age(), srp))
1462 
1463  !> Interpolation plots can be saved in the @ref intro_debug_mode
1464  !! "debug mode" using this plotting command:
1465  !! commondata::debug_interpolate_plot_save().
1466  !! @warning Involves **huge** number of plots, should normally be
1467  !! disabled.
1471  ipol_value=real(this%get_age(), srp), &
1472  algstr="DDPINTERPOL", &
1473  output_file="plot_debug_sex_steroid_incr_factor_" // &
1474  tostr(global_time_step_model_current) // &
1475  mmdd // "_a_"// trim(this%individ_label()) // &
1476  "_" // rand_string(label_length, label_cst,label_cen) &
1477  // ps )
1478 
1479  end function steroid_factor_age
1480 
1481  !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1482  !> Function calculating the value of the sex steroid increment factor that
1483  !! depends on the agent's **body length**.
1484  !! Calculate the steroid increment factor. It is set as a nonparametric
1485  !! relationship that is set by a linear interpolation LINTERPOL (or
1486  !! DDPINTERPOL) of a parameter grid values. The increment of the sex
1487  !! steroid hormones depends on the **length** of the agent: it is very
1488  !! slight in small agents, e.g. at the early stage of the ontogeny, but
1489  !! increases in larger agents up to `BODY_LENGTH_MAX`.
1490  function steroid_factor_len() result (value_out)
1491  real(srp) :: value_out
1492 
1493  !> Calculate the steroid increment factor. It is set as a nonparametric
1494  !! relationship that is set by a linear interpolation LINTERPOL (or
1495  !! DDPINTERPOL) of a parameter grid values. The increment of the sex
1496  !! steroid hormones depends on the **length** of the agent: it is very
1497  !! slight in small agents, e.g. at the early stage of the ontogeny, but
1498  !! increases in larger agents up to `BODY_LENGTH_MAX`.
1499  !! @image html img_doxy_steroid_fact_length.svg
1500  !! @image latex img_doxy_steroid_fact_length.eps "Steroid increment factor by body length" width=14cm
1501  value_out = ddpinterpol(sex_steroids_increment_factor_len_curve_abscissa, &
1503  real(this%get_length(), srp))
1504 
1505  !> Interpolation plots can be saved in the @ref intro_debug_mode
1506  !! "debug mode" using this plotting command:
1507  !! commondata::debug_interpolate_plot_save().
1508  !! @warning Involves **huge** number of plots, should normally be
1509  !! disabled.
1513  ipol_value=real(this%get_length(), srp), &
1514  algstr="DDPINTERPOL", &
1515  output_file="plot_debug_sex_steroid_incr_factor_" // &
1516  tostr(global_time_step_model_current) // &
1517  mmdd // "_a_"// trim(this%individ_label()) // &
1518  "_" // rand_string(label_length, label_cst,label_cen) &
1519  // ps )
1520 
1521  end function steroid_factor_len
1522 
1523  end subroutine sex_steroids_update_increment
1524 
1525  !-----------------------------------------------------------------------------
1526  !> Check if the body mass is smaller than the birth body mass or structural
1527  !! body mass.
1528  !! An agent dies of starvation if either of these conditions is met:
1529  !! - its body mass falls below half the birth mass;
1530  !! - below the structural mass, which is defined as half the
1531  !! historic maximum body mass of the individual;
1532  !! - energy reserves fall below 1/4 of historical maximum value;
1533  !! - body mass is below the hard limit BODY_MASS_MIN.
1534  ! @warning We use *internal object-properties* here instead of get-functions
1535  ! for brevity. Also, all raw components used here are within-object:
1536  ! `body_mass`, `stomach_content_mass`, `body_mass_birth`
1537  ! `body_mass_maximum`, `energy_current`, energy_maximum`.
1538  elemental function body_mass_is_starvation_check (this) &
1539  result(is_starved_to_death)
1540  class(condition), intent(in) :: this
1541  !> @return Returns a logical flag: TRUE if starved, FALSE otherwise.
1542  logical :: is_starved_to_death
1543 
1544  !> The `the_body::is_starved()` backend function (non-OO) is called to
1545  !! check the starvation condition.
1546  if ( is_starved( this%body_mass, this%stomach_content_mass, &
1547  this%body_mass_birth, this%body_mass_maximum, &
1548  this%energy_current, this%energy_maximum) ) then
1549  is_starved_to_death = .true.
1550  else
1551  is_starved_to_death = .false.
1552  end if
1553 
1554  end function body_mass_is_starvation_check
1555 
1556  !-----------------------------------------------------------------------------
1557  !> This is the backend logical function that checks if the agent is starved.
1558  !! It is called by the `condition::starved_death()` =>
1559  !! `the_body::body_mass_is_starvation_check()` procedure.
1560  !! @note Note that this function is not type-bound (non-OO).
1561  elemental function is_starved ( body_mass, stomach_content_mass, &
1562  body_mass_birth, body_mass_maximum, &
1563  energy_current, energy_maximum) &
1564  result(starved)
1565  !> @param[in] body_mass the current body mass of the agent.
1566  real(srp), intent(in) :: body_mass
1567  !> @param[in] stomach_content_mass the mass of the stomach content of the
1568  !! agent.
1569  real(srp), intent(in) :: stomach_content_mass
1570  !> @param[in] body_mass_birth body mass of the agent at birth.
1571  real(srp), intent(in) :: body_mass_birth
1572  !> @param[in] body_mass_maximum the historical maximum body mass of
1573  !! the agent.
1574  real(srp), intent(in) :: body_mass_maximum
1575  !> @param[in] energy_current the current level of energy.
1576  real(srp), intent(in) :: energy_current
1577  !> @param[in] energy_maximum the historical maximum level of energy.
1578  real(srp), intent(in) :: energy_maximum
1579  !> @returns TRUE if the input conditions make the agent starved to death.
1580  !! Otherwise returns FALSE.
1581  logical :: starved
1582 
1583  !> ### Conditions of severe starvation ###
1584  !> An agent is considered starving to death if either of these conditions
1585  !! is met:
1586  !! - its body mass falls below half the birth mass;
1587  !! - below the structural mass, which is defined as half the
1588  !! historic maximum body mass of the individual;
1589  !! - energy reserves fall below 1/4 of historical maximum value;
1590  !! - body mass is below the hard limit BODY_MASS_MIN.
1591  if ( body_mass - stomach_content_mass < body_mass_birth/2.0_srp .or. &
1592  body_mass - stomach_content_mass < body_mass_maximum/2.0_srp .or. &
1593  energy_current < energy_maximum/4.0_srp .or. &
1594  body_mass < body_mass_min ) then
1595  starved = .true.
1596  else
1597  starved = .false.
1598  end if
1599 
1600  end function is_starved
1601 
1602  !-----------------------------------------------------------------------------
1603  !> Digestion. Stomach contents S(t) is emptied by a constant fraction each
1604  !! time step @f[ S_{t+1} = S_{t} - S_{t} \frac{ K }{\Omega } , @f]
1605  !! where @f$ K @f$ is the *stomach content emptify factor* parameter
1606  !! (`commondata::stomach_content_emptify_factor`) and @f$ \Omega @f$ is the
1607  !! lifespan (`commondata::lifespan` parameter).
1608  !! The calculation calls the backend function for
1609  !! @f$ \Delta S = S_{t} \frac{ K }{\Omega } @f$:
1610  !! `the_body::stomach_emptify_backend()`.
1611  !> @note Should be calculated at the end of model time step.
1612  ! @warning We use internal object-properties here instead of get-functions
1613  ! for brevity. Also, all raw components used here are within-object:
1614  ! `stomach_content_mass`.
1615  elemental subroutine stomach_content_mass_emptify_step(this)
1616  class(condition), intent(inout) :: this
1617 
1618  this%stomach_content_mass = &
1619  max( 0.0_srp, &
1620  this%stomach_content_mass - &
1621  stomach_emptify_backend(this%stomach_content_mass) )
1622 
1623  end subroutine stomach_content_mass_emptify_step
1624 
1625  !-----------------------------------------------------------------------------
1626  !> The backend engine for calculating the stomach content mass decrement as
1627  !! a consequence of *digestion*. Stomach contents S(t) is emptied by a
1628  !! constant fraction each time step @f$ \Delta S @f$:
1629  !! @f[ \Delta S = S_{t} \frac{ K }{\Omega } , @f] where @f$ K @f$
1630  !! is the *stomach content emptify factor* parameter
1631  !! (`commondata::stomach_content_emptify_factor`) and @f$ \Omega @f$ is the
1632  !! lifespan (`commondata::lifespan` parameter).
1633  elemental function stomach_emptify_backend(stomach_content_mass) &
1634  result(stomach_decrement_digestion)
1635  !> @param[in] stomach_content_mass Current mass of the stomach contents.
1636  real(srp), intent(in) :: stomach_content_mass
1637  !> @return The decrement value
1638  real(srp) :: stomach_decrement_digestion
1639 
1640  stomach_decrement_digestion = &
1641  stomach_content_mass * stomach_content_emptify_factor / lifespan
1642 
1643  end function stomach_emptify_backend
1644 
1645  !-----------------------------------------------------------------------------
1646  !> Update the energy reserves of the agent based on its current mass and
1647  !! length. This subroutine should be called after any event that can change
1648  !! the mass or/and length of the agent, e.g. food consumption.
1649  elemental subroutine condition_energy_update_after_growth(this)
1650  class(condition), intent(inout) :: this
1651 
1652  !> Update the energy reserves. This is done by calling the standard
1653  !! function energy_reserve()
1654  this%energy_current = energy_reserve( this%body_mass, this%body_length )
1655 
1656  !> And also update the historical maximum value, if the current
1657  !! energy reserves value exceeds the maximum.
1658  if (this%energy_current > this%energy_maximum) &
1659  this%energy_maximum = this%energy_current
1660 
1662 
1663  !-----------------------------------------------------------------------------
1664  !> The standard cost of swimming is a diagnostic function that shows the cost,
1665  !! in units of the body mass, incurred if the agent passes a distance equal
1666  !! to commondata::lifespan units of its body length.
1667  elemental function cost_swimming_standard(this, steps) result (cost_out)
1668  class(condition), intent(in) :: this
1669  !> @param[in] steps is the optional number of steps of the agent length
1670  !! the agent walks. Default value is commondata::lifespan (i.e.
1671  !! the whole lifespan).
1672  integer, optional, intent(in) :: steps
1673  !> @return The cost of swimming in terms of the agent's current body mass.
1674  real(srp) :: cost_out
1675 
1676  ! Local copies of optionals
1677  integer :: steps_loc
1678 
1679  ! Check erroneous value of body mass, this results in a
1680  ! commondata::missing standard cost.
1681  if (this%body_mass < zero ) then
1682  cost_out = missing
1683  return
1684  end if
1685 
1686  if (present(steps)) then
1687  steps_loc = steps
1688  else
1689  steps_loc = lifespan
1690  end if
1691 
1692  cost_out = this%cost_swim( distance=this%get_length(), &
1693  exponent=swimming_cost_exponent_laminar ) * &
1694  real(steps_loc, srp) / this%get_mass()
1695 
1696  end function cost_swimming_standard
1697 
1698  !-----------------------------------------------------------------------------
1699  !> Calculate the energetic cost of reproduction in terms of the **body mass**
1700  !! of the this agent. The energetic cost of reproduction is obtained as a
1701  !! specific fixed fraction of the current body mass of the agent defined by
1702  !! the `commondata::reproduction_cost_body_mass` parameter.
1703  elemental function reproduction_cost_energy_fix(this) result(repr_cost_mass)
1704  class(reproduction), intent(in) :: this
1705  !> @returns Returns the energetic cost of reproduction for the this agent.
1706  real(srp) :: repr_cost_mass
1707 
1708  repr_cost_mass = this%get_mass() * reproduction_cost_body_mass_fix
1709 
1710  end function reproduction_cost_energy_fix
1711 
1712  !-----------------------------------------------------------------------------
1713  !> Calculate the energetic cost of reproduction in terms of the **body mass**
1714  !! of the this agent. The energetic cost of reproduction is different in
1715  !! males and females.
1716  function reproduction_cost_energy_dynamic(this) result(repr_cost_mass)
1717  class(reproduction), intent(in) :: this
1718  !> @returns Returns the energetic cost of reproduction for the this agent.
1719  real(srp) :: repr_cost_mass
1720 
1721  ! Local variables
1722  real(srp) :: offspring_mass
1723 
1724  !> ### Implementation details ###
1725  !> **First,** calculate the overall mass of the offspring that are
1726  !! produced as a result of this reproduction event @f$ \mu @f$. This
1727  !! is done using the procedure `reproduction::offspring_mass`
1728  !! (=> `the_body::reproduction_mass_offspring_calc`). The total
1729  !! mass of the offspring serves as a baseline for calculating the
1730  !! overall cost of reproduction.
1731  offspring_mass = this%offspring_mass()
1732 
1733  !> **Second,** calculate the cost of reproduction as a sum of
1734  !! two components:
1735  !! - component that scales with the total mass of the offspring
1736  !! @f$ \mu @f$;
1737  !! - component that scales with the body mass of the agent @f$ M @f$.
1738  !! .
1739  !> There are two versions of this function implemented:
1740  !! - `::cost_full()` where the cost component that scales with the
1741  !! agent's body mass is calculated from the full agent's mass *not
1742  !! subtracting* the total mass of the offspring:
1743  !! @f[ C = \mu \cdot \phi + M \cdot \varphi , @f]
1744  !! - `::cost_residual()` where the cost component that scales with
1745  !! the agent's body mass is calculated from the agent's *residual*
1746  !! body mass *after subtracting* the total mass of the offspring:
1747  !! @f[ C = \mu \cdot \phi + (M - \mu \cdot \phi ) \cdot \varphi , @f]
1748  !! .
1749  !! where @f$ \phi @f$ and @f$ \varphi @f$ are the scaling factors
1750  !! that are set by the following sex-specific parameter values:
1751  !! Scaling factor of the offspring mass component @f$ \phi @f$:
1752  !! - `commondata::reproduction_cost_offspring_fract_male`;
1753  !! - `commondata::reproduction_cost_offspring_fract_female`.
1754  !! .
1755  !! Scaling factor of the agent's body mass component @f$ \varphi @f$:
1756  !! - `commondata::reproduction_cost_body_mass_factor_male`;
1757  !! - `commondata::reproduction_cost_body_mass_factor_female`.
1758  !! .
1759  !> ### Notes ###
1760  !> This allows setting the cost of reproduction in a sex-specific
1761  !! way. For males, for example, the component proportional to the
1762  !! total offspring mass is set to some small value (@f$ \phi \leq 1.0 @f$,
1763  !! whereas in females, who carry the eggs, this cost is at least equal to
1764  !! the full offspring mass (@f$ \phi \geq 1.0 @f$). On the other hand,
1765  !! the cost component that is proportional to the agent body mass can
1766  !! be higher in males that in females due to competition for mates
1767  !! (@f$ \varphi_{males} \geq \varphi_{females} @f$). Various patterns
1768  !! can be implemented by varying the sex-specific scaling parameters and
1769  !! the two versions of the backend procedure (`::cost_full()`,
1770  !! `::cost_residual()`).
1771  if ( this%is_male() ) then
1774  else
1777  end if
1778 
1779  contains
1780  !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1781  !> Backend function that is called in
1782  !! `the_body::reproduction_cost_energy_dynamic()`.
1783  !> Calculate the cost of reproduction as a sum of
1784  !! two components: (a) component that scales with the total mass
1785  !! of the offspring @f$ \mu @f$; (b) component that scales with the
1786  !! body mass of the agent @f$ M @f$.
1787  !! @f[ C = \mu \cdot \phi + M \cdot \varphi , @f]
1788  !! where @f$ \phi @f$ and @f$ \varphi @f$ are the scaling factors
1789  !! that are set by the following sex-specific parameter values:
1790  !! Scaling factor of the offspring mass component @f$ \phi @f$:
1791  !! - `commondata::reproduction_cost_offspring_fract_male`;
1792  !! - `commondata::reproduction_cost_offspring_fract_female`.
1793  !! .
1794  !! Scaling factor of the agent's body mass component @f$ \varphi @f$:
1795  !! - `commondata::reproduction_cost_body_mass_factor_male`;
1796  !! - `commondata::reproduction_cost_body_mass_factor_female`.
1797  !! .
1798  !! @note In this version, the cost component that scales with the agent's
1799  !! body mass is calculated from the agent's mass not subtracting
1800  !! the total mass of the offspring:@f$ M \cdot \varphi @f$.
1801  pure function cost_full (offspring_mass_fact, agent_mass_fact) result (cost)
1802  !> @param[in] offspring_mass_fact scaling factor of the offspring mass
1803  !! component @f$ \phi @f$:
1804  !! - `commondata::reproduction_cost_offspring_fract_male`;
1805  !! - `commondata::reproduction_cost_offspring_fract_female`.
1806  !! .
1807  real(srp), intent(in) :: offspring_mass_fact
1808  !> @param[in] agent_mass_fact scaling factor of the agent's body mass
1809  !! component @f$ \varphi @f$:
1810  !! - `commondata::reproduction_cost_body_mass_factor_male`;
1811  !! - `commondata::reproduction_cost_body_mass_factor_female`.
1812  !! .
1813  real(srp), intent(in) :: agent_mass_fact
1814  !> @return The cost of reproduction.
1815  real(srp) :: cost
1816 
1817  ! Using **full** body mass of the agent.
1818  cost = offspring_mass * offspring_mass_fact + &
1819  this%get_mass() * agent_mass_fact
1820 
1821  end function cost_full
1822 
1823  !- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1824  !> Backend function that is called in
1825  !! `the_body::reproduction_cost_energy_dynamic()`.
1826  !> Calculate the cost of reproduction as a sum of
1827  !! two components: (a) component that scales with the total mass
1828  !! of the offspring @f$ \mu @f$; (b) component that scales with the
1829  !! body mass of the agent @f$ M @f$.
1830  !! @f[ C = \mu \cdot \phi + (M - \mu \cdot \phi ) \cdot \varphi , @f]
1831  !! where @f$ \phi @f$ and @f$ \varphi @f$ are the scaling factors
1832  !! that are set by the following sex-specific parameter values:
1833  !! Scaling factor of the offspring mass component @f$ \phi @f$:
1834  !! - `commondata::reproduction_cost_offspring_fract_male`;
1835  !! - `commondata::reproduction_cost_offspring_fract_female`.
1836  !! .
1837  !! Scaling factor of the agent's body mass component @f$ \varphi @f$:
1838  !! - `commondata::reproduction_cost_body_mass_factor_male`;
1839  !! - `commondata::reproduction_cost_body_mass_factor_female`.
1840  !! .
1841  !! @note In this version, the cost component that scales with the agent's
1842  !! *residual* body mass is calculated from the agent's mass after
1843  !! subtracting the total mass of the offspring:
1844  !! @f$ (M - \mu \cdot \phi ) \cdot \varphi @f$.
1845  pure function cost_residual (offspring_mass_fact, agent_mass_fact) result (cost)
1846  !> @param[in] offspring_mass_fact scaling factor of the offspring mass
1847  !! component @f$ \phi @f$:
1848  !! - `commondata::reproduction_cost_offspring_fract_male`;
1849  !! - `commondata::reproduction_cost_offspring_fract_female`.
1850  !! .
1851  real(srp), intent(in) :: offspring_mass_fact
1852  !> @param[in] agent_mass_fact scaling factor of the agent's body mass
1853  !! component @f$ \varphi @f$:
1854  !! - `commondata::reproduction_cost_body_mass_factor_male`;
1855  !! - `commondata::reproduction_cost_body_mass_factor_female`.
1856  !! .
1857  real(srp), intent(in) :: agent_mass_fact
1858  !> @return The cost of reproduction.
1859  real(srp) :: cost
1860 
1861  ! Using **residual body mass** of the agent after subtracting
1862  ! the fraction that scales with the offspring mass.
1863  cost = offspring_mass * offspring_mass_fact + &
1864  (this%get_mass() - offspring_mass * offspring_mass_fact) &
1865  * agent_mass_fact
1866 
1867  end function cost_residual
1868 
1870 
1871  !-----------------------------------------------------------------------------
1872  !> Calculate the costs of unsuccessful reproduction. This is calculated as
1873  !! a fraction of the normal cost of reproduction returned by the function
1874  !! `reproduction::reproduction_cost()`. Reproduction can
1875  !! be unsuccessful for various reasons: insufficient reserves
1876  !! (reproduction results in starvation death) or stochastic no success.
1877  function reproduction_cost_unsuccessful_calc (this, cost_factor) &
1878  result(repr_cost_mass)
1879  class(reproduction), intent(in) :: this
1880  !> @param[in] cost_factor Optional cost factor multiplier the normal
1881  !! cost of reproduction is applied to. If absent, the default
1882  !! value set by the `commondata::reproduction_cost_unsuccess`
1883  !! parameter is used.
1884  real(srp), optional, intent(in) :: cost_factor
1885  !> @returns Returns the energetic cost of unsuccessful reproduction for
1886  !! the 'this' agent.
1887  real(srp) :: repr_cost_mass
1888 
1889  !> Unsuccessful reproduction attempt results in a cost,
1890  !! in terms of the body mass, that is a fraction of the normal cost
1891  !! of reproduction: the fraction is defined by the parameter
1892  !! `commondata::reproduction_cost_unsuccess` in `COMMONDATA`.
1893  !> The body mass of the agent is then reduced to take this fraction of
1894  !! the full cost of reproduction. This updated value is saved into
1895  !! the body mass history stack (`update_history` parameter is `TRUE`).
1896  if(present(cost_factor)) then
1897  repr_cost_mass = this%reproduction_cost() * cost_factor
1898  else
1899  repr_cost_mass = this%reproduction_cost() * reproduction_cost_unsuccess
1900  end if
1901 
1903 
1904  !-----------------------------------------------------------------------------
1905  !> Initialise the reproduction object for the agent. Everything is set to
1906  !! zero.
1907  elemental subroutine reproduction_init_zero(this)
1908  class(reproduction), intent(inout) :: this
1909 
1910  !> Set the total number of reproductions and offspring to zero.
1911  this%n_reproductions = 0
1912  this%n_offspring = 0
1913 
1914  end subroutine reproduction_init_zero
1915 
1916  !-----------------------------------------------------------------------------
1917  !> Get the number of reproductions for this agent.
1918  elemental function reproduction_n_reproductions_get(this) result (n_repr)
1919  class(reproduction), intent(in) :: this
1920  !> @return The number of reproductions the agent had.
1921  integer :: n_repr
1922 
1923  n_repr = this%n_reproductions
1924 
1926 
1927  !-----------------------------------------------------------------------------
1928  !> Set the number of reproductions for the agent.
1929  elemental subroutine reproduction_n_reproductions_set(this, n_repr)
1930  class(reproduction), intent(inout) :: this
1931  !> @param[in] n_repr The total number of reproductions for this agent.
1932  integer, intent(in) :: n_repr
1933 
1934  this%n_reproductions = n_repr
1935 
1936  end subroutine reproduction_n_reproductions_set
1937 
1938  !-----------------------------------------------------------------------------
1939  !> Get the number of offspring
1940  elemental function reproduction_n_offspring_get(this) result (n_offspr)
1941  class(reproduction), intent(in) :: this
1942  !> @return The number of offspring the agent had during its lifespan.
1943  integer :: n_offspr
1944 
1945  n_offspr = this%n_offspring
1946 
1947  end function reproduction_n_offspring_get
1948 
1949  !-----------------------------------------------------------------------------
1950  !> Set the number of offspring for the agent.
1951  elemental subroutine reproduction_n_offspring_set(this, n_offspr)
1952  class(reproduction), intent(inout) :: this
1953  !> @param[in] n_offspr The number of offspring to set for this agent.
1954  integer, intent(in) :: n_offspr
1955 
1956  this%n_offspring = n_offspr
1957 
1958  end subroutine reproduction_n_offspring_set
1959 
1960  !-----------------------------------------------------------------------------
1961  !> Increment the number of reproductions and offspring for this agent.
1962  subroutine reproduction_n_increment(this, add_repr, average_mass_offspring)
1963  class(reproduction), intent(inout) :: this
1964  !> @param[in] add_repr Increment the total number of reproductions for
1965  !! this agent by this number; if not provided as a dummy
1966  !! parameter assume increment by one.
1967  !! **Note:** Varying the number of reproductions allows
1968  !! implementation of multiple fertilisations by a male,
1969  !! resulting in `add_repr`>1 during a single reproduction
1970  !! event, provided several females are present in the male's
1971  !! perception object. This allows modelling sexual asymmetries.
1972  integer, optional, intent(in) :: add_repr
1973  !> @param[in] average_mass_offspring optional average body mass of the
1974  !! ` offspring. If not provided, back calculated from the
1975  !! Fulton's condition factor and the body length of the agents
1976  !! at init (birth) using the `the_body::length2mass()` function.
1977  real(SRP), optional, intent(in) :: average_mass_offspring
1978 
1979  ! Local variables
1980  integer :: add_repr_here
1981 
1982  !> ### Implementation details ###
1983  !> **First,** check if the `add_repr` increment parameter is provided.
1984  !! If not, set it to the default value = 1.
1985  if (present(add_repr)) then
1986  add_repr_here = add_repr
1987  else
1988  add_repr_here = 1
1989  end if
1990 
1991  !> **Second,** increment the number of reproductions for this agent (data
1992  !! component, `reproduction::n_reproductions`) by the increment parameter.
1993  this%n_reproductions = this%n_reproductions + add_repr_here
1994 
1995  !> **Third,** calculate the number of the offspring
1996  !! that result from this/these reproduction occurrence(s) and
1997  !! increment the lifetime number `reproduction::n_offspring` for the
1998  !! agent respectively. The number of offspring is calculated
1999  !! using the function `reproduction::offspring_number()`
2000  !! (`the_body::reproduction_n_offspring_calc()`).
2001  !! The average mass of the offspring (`average_mass_offspring`), if
2002  !! provided, transfers into the above backend function.
2003  if (present(average_mass_offspring)) then
2004  this%n_offspring = this%n_offspring + &
2005  this%offspring_number(average_mass_offspring) &
2006  * add_repr_here
2007  else
2008  this%n_offspring = this%n_offspring + &
2009  this%offspring_number() * add_repr_here
2010  end if
2011 
2012  end subroutine reproduction_n_increment
2013 
2014  !-----------------------------------------------------------------------------
2015  !> Calculate the number of offspring per a single reproduction as a
2016  !! function of the agent's body mass.
2017  function reproduction_n_offspring_calc(this, average_mass_offspr) &
2018  result(n_offspr)
2019  class(reproduction), intent(inout) :: this
2020  !> @param[in] average_mass_offspr Optional average body mass of the
2021  !! offspring (@f$ \mu_{o} @f$, see below).
2022  real(srp), optional, intent(in) :: average_mass_offspr
2023  !> @return Returns the number of offspring per single
2024  !! reproduction.
2025  integer :: n_offspr
2026 
2027  ! Local, total body mass of all the offspring.
2028  real(srp) :: total_mass_offspring
2029 
2030  ! Local copies of optionals
2031  real(srp) :: average_mass_offspr_here
2032 
2033  !> ### Implementation details ###
2034  !> Initially check if the average mass of newborn agents @f$ \mu_{o} @f$
2035  !! is provided as a dummy parameter to this function call. If not,
2036  !! calculate a guess of the average mass from the Fulton's condition
2037  !! factor and the body length parameters of the agents at init (birth)
2038  !! using the `the_body::length2mass()` function.
2039  if (present(average_mass_offspr)) then
2040  average_mass_offspr_here = average_mass_offspr
2041  else
2042  average_mass_offspr_here = length2mass(energy_init, body_length_init)
2043  end if
2044 
2045  !> The number of offspring produced at a single reproduction
2046  !! scales with the body mass of the agent.
2047  !> **First,** all the offspring comprise the maximum combined fraction
2048  !! of the agent's body mass @f$ \phi \cdot M_{agent} @f$, this fraction
2049  !! @f$ \phi @f$ is obtained by a nonparametric relationship defined by
2050  !! the the interpolation grid:
2051  !! - `commondata::reproduct_body_mass_offspr_abscissa`
2052  !! - `commondata::reproduct_body_mass_offspr_ordinate`
2053  !! .
2054  !! The total mass of the offspring (@f$ \phi \cdot M_{agent} @f$) is
2055  !! calculated in the procedure `reproduction::offspring_mass()` (=>
2056  !! `the_body::reproduction_mass_offspring_calc()`).
2057  total_mass_offspring = this%offspring_mass()
2058 
2059  !> **Second,** the number of the offspring with the overall mass
2060  !! @f$ \phi \cdot M_{agent} @f$ is calculated as the fraction:
2061  !! @f[ \frac{ \phi \cdot M_{agent} }{ \mu_{o} } , @f] where
2062  !! @f$ \mu_{o} @f$ is the average mass of a single offspring
2063  !! at init (birth). The `floor` Fortran intrinsic function is
2064  !! used to calculate the integer value from this ratio. This
2065  !! guarantees that the number of offspring returned is the
2066  !! *lowest* integer value resulting from the above ratio.
2067  n_offspr = floor(total_mass_offspring / average_mass_offspr_here)
2068 
2069  end function reproduction_n_offspring_calc
2070 
2071  !-----------------------------------------------------------------------------
2072  !> Determine if the agent's hormonal system is ready for reproduction.
2074  result(is_ready)
2075  class(reproduction), intent(in) :: this
2076  !> @return TRUE if the agent is ready to reproduce by sufficiently high
2077  !! level of gonadal steroids or FALSE otherwise.
2078  logical :: is_ready
2079 
2080  !> ### Implementation notes ###
2081  !> Determine if the agent's hormonal system is ready for reproduction, that
2082  !! is, its current level of sex steroids @f$ \sigma_{i} @f$ exceeds the
2083  !! baseline (initially determined by the genome) @f$ \sigma_{0} @f$ by a
2084  !! factor @f$ \nu @f$ determined by the parameter
2085  !! commondata::sex_steroids_reproduction_threshold:
2086  !! @f[ \sigma_{i} > \nu \sigma_{0} . @f]
2087  !! If the level of sex steroids is insufficient, reproduction is
2088  !! impossible and FALSE is returned.
2089  is_ready = .false.
2090  if ( this%is_male() .and. &
2091  this%testosterone_get() > this%testosterone_base_get() &
2093  is_ready = .true.
2094  else if ( &
2095  this%is_female() .and. &
2096  this%estrogen_get() > this%estrogen_base_get() &
2098  is_ready = .true.
2099  end if
2100 
2102 
2103  !-----------------------------------------------------------------------------
2104  !> Calculate the total mass of all offspring produced by this agent
2105  !! during a single reproduction event.
2106  function reproduction_mass_offspring_calc (this) result (offspr_mass)
2107  class(reproduction), intent(in) :: this
2108  !> @return Total mass of all offspring produced by the agent during a
2109  !! specific reproduction event.
2110  real(srp) :: offspr_mass
2111 
2112  !> ### Implementation details ###
2113  !> The total mass of all offspring produced at a single reproduction
2114  !! scales with the body mass of the agent and is obtained by
2115  !! a non-parametric relationship involving non-linear interpolation.
2116  !> The combined offspring mass is calculated as a fraction of the agent's
2117  !! body mass @f$ M_{agent} @f$ using this equation:
2118  !! @f[ \phi \cdot M_{agent} , @f] where @f$ \phi @f$ is the fraction
2119  !! coefficient obtained by a nonparametric relationship defined by
2120  !! the the interpolation grid
2121  !! - `commondata::reproduct_body_mass_offspr_abscissa`
2122  !! - `commondata::reproduct_body_mass_offspr_ordinate`
2123  !! .
2124  !! @image html img_doxy_aha-reprod_mass_fract.svg
2125  !! @image latex img_doxy_aha-reprod_mass_fract.eps "Offspring fraction of body mass" width=14cm
2126  offspr_mass = this%body_mass * &
2127  ddpinterpol( reproduct_body_mass_offspr_abscissa, &
2129  this%body_mass )
2130 
2131  !> Interpolation plots can be saved in the @ref intro_debug_mode
2132  !! "debug mode" using this plotting command:
2133  !! `commondata::debug_interpolate_plot_save()`.
2134  !! @warning Involves **huge** number of plots, should normally be
2135  !! disabled.
2139  ipol_value=this%body_mass, algstr="DDPINTERPOL", &
2140  output_file="plot_debug_reprod_mass_fract_" // &
2141  tostr(global_time_step_model_current) // &
2142  mmdd // "_a_"// trim(this%individ_label()) // &
2143  "_" // rand_string(label_length, label_cst,label_cen) &
2144  // ps )
2145 
2147 
2148 end module the_body
Simple history stack function, add to the end of the stack. We need only to add components on top (en...
Definition: m_common.f90:5292
Convert cm to m.
Definition: m_common.f90:5306
Sigmoidal relationship between environmental factor and the organism response, as affected by the gen...
Definition: m_common.f90:5269
Convert m to cm.
Definition: m_common.f90:5319
Force a value within the range set by the vmin and vmax dummy parameter values.
Definition: m_common.f90:5350
Calculate visual range of predator using Dag Aksnes's procedures srgetr(), easyr() and deriv().
Definition: m_env.f90:738
pure real(srp) function cost_residual(offspring_mass_fact, agent_mass_fact)
Backend function that is called in the_body::reproduction_cost_energy_dynamic(). Calculate the cost o...
Definition: m_body.f90:1846
real(srp) function steroid_factor_len()
Function calculating the value of the sex steroid increment factor that depends on the agent's body l...
Definition: m_body.f90:1491
real(srp) function steroid_factor_age()
Function calculating the value of the sex steroid increment factor that depends on the agent's age....
Definition: m_body.f90:1451
pure real(srp) function cost_full(offspring_mass_fact, agent_mass_fact)
Backend function that is called in the_body::reproduction_cost_energy_dynamic(). Calculate the cost o...
Definition: m_body.f90:1802
COMMONDATA – definitions of global constants and procedures.
Definition: m_common.f90:1497
real(srp), parameter, public stomach_content_init_cv
Set the coefficient of variation for the stomach capacity at init.
Definition: m_common.f90:3156
real(srp), parameter, public cost_factor_foraging_smr
Set the cost of foraging in terms of SMR.
Definition: m_common.f90:3165
real(srp), parameter, public body_length_max
Maximum body length.
Definition: m_common.f90:2121
real(srp), parameter, public control_unselected_gerror_cv
Genotype to phenotype initialisation, Gaussian error parameter. Coefficient of variation for the cont...
Definition: m_common.f90:3274
real(srp), parameter, public smr_init
This is the initial value of SMR that goes through the gamma2gene.
Definition: m_common.f90:3306
real(srp), parameter, public tolerance_low_def_srp
Default value of low tolerance (high precision). This is the standard commondata::srp precision....
Definition: m_common.f90:1671
character(len= *), parameter, public ps
Standard file extension for debug and other PostScript plots.
Definition: m_common.f90:1716
real(srp), parameter, public sex_steroids_reproduction_threshold
This parameter defines the threshold of the current gonadal steroids level that should exceed the bas...
Definition: m_common.f90:4934
real(srp), dimension(*), parameter, public reproduct_body_mass_offspr_ordinate
The array defining the ordinate (Y) of the nonparametric function curve that defines the relationship...
Definition: m_common.f90:2225
integer, parameter, public srp
Definition of the standard real type precision (SRP).
Definition: m_common.f90:1551
logical, dimension(max_nalleles, n_chromosomes), parameter, public control_unselected_genotype_phenotype
The initial value of the control unselected trait. This trait is is genetically determined but is not...
Definition: m_common.f90:3244
real(srp), parameter, public smr_min
Minimum SMR value, anything lower is not allowed.
Definition: m_common.f90:3313
elemental real(srp) function cv2variance(cv, mean)
Calculate the variance from the coefficient of variation.
Definition: m_common.f90:6956
real(srp), parameter swimming_cost_exponent_laminar
Default swimming cost body mass exponent parameter for laminar flow. See doi:10.1242/jeb....
Definition: m_common.f90:3318
real(srp), parameter, public linear_growth_exponent
Growth exponent linking linear growth and body mass growth. Based on Fulton's condition factor "cube ...
Definition: m_common.f90:3114
integer, parameter, public sex_steroids_check_history
The number of the latest historical values that are checked for change when setting an increment of t...
Definition: m_common.f90:3024
real(srp), parameter, public body_length_init
The initial value of body length, the average (gon-genetic).
Definition: m_common.f90:3232
real(srp), parameter, public smr_gerror_cv
Genotype to phenotype initialisation, Gaussian error parameter. Coefficient of variation for the SMR_...
Definition: m_common.f90:3310
real(srp), parameter, public reproduction_cost_unsuccess
The energetic cost of unsuccessful reproduction in terms of the agent's body mass lost....
Definition: m_common.f90:2204
logical, dimension(max_nalleles, n_chromosomes), parameter, public smr_genotype_phenotype
The initial value of the standard metabolic rate (SMR) at birth is genetically determined....
Definition: m_common.f90:3281
real(srp), parameter, public reproduction_cost_body_mass_fix
The energetic cost of reproduction in terms of the agent's body mass loss.
Definition: m_common.f90:2175
integer, parameter, public label_length
The length of standard character string labels. We use labels for various objects,...
Definition: m_common.f90:1736
real(srp), parameter, public reproduction_cost_body_mass_factor_female
The component of the energetic cost of reproduction in females that is proportional to the agent's bo...
Definition: m_common.f90:2198
real(srp), parameter swimming_cost_exponent_turbulent
Default swimming cost body mass exponent parameter for turbulent flow. See doi:10....
Definition: m_common.f90:3323
real(srp), parameter, public max_stomach_capacity_def
Set the maximum stomach capacity default value – fraction of the body mass available for food....
Definition: m_common.f90:3142
real(srp), parameter, public missing
Numerical code for missing and invalid real type values.
Definition: m_common.f90:1699
subroutine log_dbg(message_string, procname, modname)
LOG_DBG: debug message to the log. The message goes to the logger only when running in the DEBUG mode...
Definition: m_common.f90:9171
real(srp), parameter, public body_mass_min
Minimum possible body mass, hard limit.
Definition: m_common.f90:2126
real(srp), parameter, public stomach_content_emptify_factor
Stomach content emptify factor at each step.
Definition: m_common.f90:3148
real(srp), parameter, public living_cost
Living cost in terms of food consumed. metabolic costs, p roportional to body size.
Definition: m_common.f90:3105
integer, parameter, public history_size_agent_prop
History stack size for the agent's basic properties, such as body length and body mass....
Definition: m_common.f90:3101
logical, parameter, public true
Safety parameter avoid errors in logical values, so we can now refer to standard Fortran ....
Definition: m_common.f90:1632
real(srp), parameter, public energy_init
This is the initial value of the energy reserves, non-genetic mean.
Definition: m_common.f90:3197
integer, parameter, public label_cen
Definition: m_common.f90:1743
character(len=:), allocatable, public, protected mmdd
MMDD tag, year, month and day, used in file names and outputs. The value of the tag should be obtaine...
Definition: m_common.f90:2052
real(srp), parameter, public zero
Some parameters should never be zero or below. In such cases they could be set to some smallest disti...
Definition: m_common.f90:1644
integer, parameter, public lifespan
Number of time steps in the agent's maximum life length.
Definition: m_common.f90:2066
real(srp), parameter, public preycontrast_default
Inherent contrast of prey, CONTRAST =1.0.
Definition: m_common.f90:2527
real(srp), parameter, public food_item_capture_prop_cost
The cost of the food item catching, in terms of the food item mass (proportional cost)....
Definition: m_common.f90:2457
real(srp), dimension(*), parameter, public reproduct_body_mass_offspr_abscissa
The array defining the abscissa (X) of the nonparametric function curve that defines the relationship...
Definition: m_common.f90:2211
real(srp), dimension(*), parameter, public linear_growth_hormone_increment_factor_curve_ordinate
The array defining the ordinate (Y) of the nonparametric function curve that defines the function lin...
Definition: m_common.f90:3134
real(srp), dimension(*), parameter, public linear_growth_hormone_increment_factor_curve_abscissa
The array defining the abscissa (X) of the nonparametric function curve that defines the function lin...
Definition: m_common.f90:3123
subroutine debug_interpolate_plot_save(grid_xx, grid_yy, ipol_value, algstr, output_file, enable_non_debug)
Produce a debug plot of the interpolation data using an external program htinterp from the HEDTOOLS t...
Definition: m_common.f90:8231
real(srp), parameter, public energy_gerror_cv
Genotype to phenotype initialisation, Gaussian error parameter. Coefficient of variation for the ENER...
Definition: m_common.f90:3201
real(srp), parameter, public food_item_size_default
Default size of a single food item.
Definition: m_common.f90:2438
real(srp), parameter, public body_length_gerror_cv
Genotype to phenotype initialisation, Gaussian error parameter. Coefficient of variation for the BODY...
Definition: m_common.f90:3236
real(srp), parameter, public body_length_min
Minimum body length possible.
Definition: m_common.f90:2118
real(srp), parameter, public control_unselected_init
The initial value of the control unselected trait that goes through the gamma2gene.
Definition: m_common.f90:3270
real(srp), parameter, public reproduction_cost_offspring_fract_female
The component of the energetic cost of reproduction in females that is proportional to the total offs...
Definition: m_common.f90:2186
integer, parameter, public label_cst
This parameter defines the range of characters that is used for generating random labels,...
Definition: m_common.f90:1743
integer, public global_time_step_model_current
The current global time step of the model. This is a global non fixed-parameter variable that is upda...
Definition: m_common.f90:2095
real(srp), parameter, public reproduction_cost_body_mass_factor_male
The component of the energetic cost of reproduction in males that is proportional to the agent's body...
Definition: m_common.f90:2192
elemental real(srp) function length2sidearea_fish(body_length)
A function linking body length with the body area in fish.
Definition: m_common.f90:5682
real(srp), dimension(*), parameter, public sex_steroids_increment_factor_age_curve_abscissa
The array defining the abscissa (X) of the nonparametric function curve that defines the relationship...
Definition: m_common.f90:3040
real(srp), dimension(*), parameter, public sex_steroids_increment_factor_len_curve_ordinate
The array defining the ordinate (Y) of the nonparametric function curve that defines the relationship...
Definition: m_common.f90:3083
real(srp), parameter, public reproduction_cost_offspring_fract_male
The component of the energetic cost of reproduction in males that is proportional to the total offspr...
Definition: m_common.f90:2180
real(srp), dimension(*), parameter, public sex_steroids_increment_factor_age_curve_ordinate
The array defining the ordinate (Y) of the nonparametric function curve that defines the relationship...
Definition: m_common.f90:3053
real(srp), dimension(*), parameter, public sex_steroids_increment_factor_len_curve_abscissa
The array defining the abscissa (X) of the nonparametric function curve that defines the relationship...
Definition: m_common.f90:3070
real(srp), parameter, public swimming_speed_cost_burst
Set the weighting factor parameter of burst swimming cost in terms of the agent body size and the dis...
Definition: m_common.f90:3162
real(srp), parameter, public stomach_content_init
Set average stomach capacity at birth/init in units of body weight,.
Definition: m_common.f90:3153
logical, parameter, public false
Definition: m_common.f90:1632
real(srp), parameter, public mass_growth_threshold
A minimum body mass increment when any linear growth is possible, in units of the body mass (e....
Definition: m_common.f90:3109
Definition the physical properties and condition of the agent.
Definition: m_body.f90:19
elemental real(srp) function stomach_content_food_gain_non_fit_v(this, food_gain)
Calculate extra food surplus mass non fitting into the stomach of the agent.
Definition: m_body.f90:1058
elemental subroutine reproduction_n_offspring_set(this, n_offspr)
Set the number of offspring for the agent.
Definition: m_body.f90:1952
elemental logical function reproduction_ready_steroid_hormones_exceed(this)
Determine if the agent's hormonal system is ready for reproduction.
Definition: m_body.f90:2075
subroutine sex_steroids_update_increment(this)
Update the level of the sex steroids.
Definition: m_body.f90:1355
subroutine condition_init_genotype(this)
Initialise the individual body condition object based on the genome values. Two alleles are selected ...
Definition: m_body.f90:355
elemental integer function reproduction_n_offspring_get(this)
Get the number of offspring.
Definition: m_body.f90:1941
character(len= *), parameter, private modname
Definition: m_body.f90:26
elemental real(srp) function body_mass_food_processing_cost_factor_smr(this, food_gain)
The fraction of the cost of the processing of the food item(s) depending on the agent SMR....
Definition: m_body.f90:1192
elemental subroutine reproduction_init_zero(this)
Initialise the reproduction object for the agent. Everything is set to zero.
Definition: m_body.f90:1908
elemental real(srp) function condition_body_mass_max_get(this)
Get historcal maximum for body mass. Standard GET-function.
Definition: m_body.f90:776
elemental subroutine condition_energy_update_after_growth(this)
Update the energy reserves of the agent based on its current mass and length. This subroutine should ...
Definition: m_body.f90:1650
elemental real(srp) function stomach_emptify_backend(stomach_content_mass)
The backend engine for calculating the stomach content mass decrement as a consequence of digestion....
Definition: m_body.f90:1635
real(srp) function reproduction_cost_energy_dynamic(this)
Calculate the energetic cost of reproduction in terms of the body mass of the this agent....
Definition: m_body.f90:1717
real(srp) function body_len_grow_calculate_increment_step(this, mass_increment)
Calculate body length increment for a time step of the model.
Definition: m_body.f90:1231
elemental logical function body_mass_is_starvation_check(this)
Check if the body mass is smaller than the birth body mass or structural body mass....
Definition: m_body.f90:1540
integer function reproduction_n_offspring_calc(this, average_mass_offspr)
Calculate the number of offspring per a single reproduction as a function of the agent's body mass.
Definition: m_body.f90:2019
elemental real(srp) function stomach_content_food_gain_non_fit_o(this, food_obj)
Calculate extra food surplus mass non fitting into the stomach of the agent.
Definition: m_body.f90:1091
elemental real(srp) function body_mass_calculate_cost_living_step(this)
Calculate the cost of living for a single model step. So the agent mass increment per a single model ...
Definition: m_body.f90:1127
real(srp) function condition_agent_visibility_visual_range(this, object_area, contrast, time_step_model)
Calculate the visibility range of this agent. Visibility depends on the size of the agent,...
Definition: m_body.f90:605
elemental real(srp) function condition_body_length_get(this)
Get current body length. Standard GET-function.
Definition: m_body.f90:561
subroutine birth_mortality_enforce_init_fixed_debug(this)
This procedure enforces selective mortality of agents at birth to avoid strong selection for energy a...
Definition: m_body.f90:464
elemental real(srp) function body_mass_processing_cost_calc_o(this, food_obj, distance_food)
Calculate the basic processing cost of catching a food item with the mass food_gain.
Definition: m_body.f90:937
elemental real(srp) function energy_reserve(m, l)
Calculate the current energy reserves (Fulton condition factor) from body mass and length.
Definition: m_body.f90:332
real(srp) function reproduction_cost_unsuccessful_calc(this, cost_factor)
Calculate the costs of unsuccessful reproduction. This is calculated as a fraction of the normal cost...
Definition: m_body.f90:1879
elemental real(srp) function condition_control_unsel_get(this)
Get current value of the control unselected trait. Standard GET-function.
Definition: m_body.f90:572
elemental real(srp) function condition_energy_current_get(this)
Get current energy reserves. Standard GET-function.
Definition: m_body.f90:539
elemental real(srp) function condition_cost_swimming_burst(this, distance, exponent)
The cost of swimming of a specific distance in terms of the actor's body mass.
Definition: m_body.f90:881
elemental integer function reproduction_n_reproductions_get(this)
Get the number of reproductions for this agent.
Definition: m_body.f90:1919
subroutine body_len_grow_do_calculate_step(this, mass_increment, update_history)
Do linear growth for one model step based on the increment function the_body::condition::len_incr().
Definition: m_body.f90:1321
subroutine condition_body_length_set_update_hist(this, value_set, update_history)
Set body length optionally updating the history stack.
Definition: m_body.f90:713
elemental subroutine condition_age_reset_zero(this)
Reset the age of the agent to zero.
Definition: m_body.f90:514
elemental real(srp) function condition_body_mass_birth_get(this)
Get historical record of body mass at birth. Standard GET-function.
Definition: m_body.f90:765
elemental subroutine condition_clean_history(this)
Cleanup the history stack of the body length and mass.
Definition: m_body.f90:490
elemental subroutine body_mass_grow_do_calculate(this, food_gain, update_history)
Do grow body mass based on food gain from a single food item adjusted for cost etc.
Definition: m_body.f90:1162
elemental subroutine stomach_content_mass_emptify_step(this)
Digestion. Stomach contents S(t) is emptied by a constant fraction each time step.
Definition: m_body.f90:1616
elemental real(srp) function reproduction_cost_energy_fix(this)
Calculate the energetic cost of reproduction in terms of the body mass of the this agent....
Definition: m_body.f90:1704
elemental real(srp) function condition_body_mass_get(this)
Get current body mass. Standard GET-function.
Definition: m_body.f90:583
subroutine reproduction_n_increment(this, add_repr, average_mass_offspring)
Increment the number of reproductions and offspring for this agent.
Definition: m_body.f90:1963
elemental integer function condition_age_get(this)
Get current age. Standard GET-function.
Definition: m_body.f90:503
elemental real(srp) function condition_energy_birth_get(this)
Get historical record of energy reserves at birth. Standard GET-function.
Definition: m_body.f90:743
elemental real(srp) function condition_body_length_birth_get(this)
Get historical record of body length at birth. Standard GET-function.
Definition: m_body.f90:754
elemental subroutine reproduction_n_reproductions_set(this, n_repr)
Set the number of reproductions for the agent.
Definition: m_body.f90:1930
elemental real(srp) function stomach_content_food_gain_fitting_o(this, food_obj, food_dist)
Calculate the value of possible food gain as fitting into the agent's stomach (or full gain if the fo...
Definition: m_body.f90:1027
elemental subroutine body_mass_adjust_living_cost_step(this)
Adjust the body mass at the end of the model step against the cost of living. We do not adjust the co...
Definition: m_body.f90:1150
elemental real(srp) function stomach_content_food_gain_fitting_v(this, food_gain, food_dist)
Calculate the value of possible food gain as fitting into the agent's stomach, or the full gain if th...
Definition: m_body.f90:991
elemental logical function is_starved(body_mass, stomach_content_mass, body_mass_birth, body_mass_maximum, energy_current, energy_maximum)
This is the backend logical function that checks if the agent is starved. It is called by the conditi...
Definition: m_body.f90:1565
elemental real(srp) real(srp) function body_mass_processing_cost_calc_v(this, food_gain, distance_food)
Calculate the basic processing cost of catching a food item with the mass food_gain.
Definition: m_body.f90:822
elemental real(srp) function cost_swimming_standard(this, steps)
The standard cost of swimming is a diagnostic function that shows the cost, in units of the body mass...
Definition: m_body.f90:1668
subroutine condition_body_mass_set_update_hist(this, value_set, update_history)
Set body mass optionally updating the history stack.
Definition: m_body.f90:674
elemental real(srp) function condition_smr_get(this)
Get current smr. Standard GET-function.
Definition: m_body.f90:787
elemental subroutine condition_age_increment(this, increment)
Increment the age of the agent by one.
Definition: m_body.f90:523
elemental real(srp) function condition_stomach_content_get(this)
Get current stomach content. Standard GET-function.
Definition: m_body.f90:798
elemental subroutine stomach_content_get_increment(this, stomach_increment)
Do increment stomach contents with adjusted (fitted) value.
Definition: m_body.f90:1206
real(srp) function reproduction_mass_offspring_calc(this)
Calculate the total mass of all offspring produced by this agent during a single reproduction event.
Definition: m_body.f90:2107
elemental real(srp) function length2mass(k, l)
This is the function to calculate the body weight from the length and the Fulton condition factor (en...
Definition: m_body.f90:309
elemental real(srp) function condition_energy_maximum_get(this)
Get historical maximum of energy reserves. Standard GET-function.
Definition: m_body.f90:550
Definition of environmental objects.
Definition: m_env.f90:19
Definition the hormonal architecture of the agent.
Definition: m_hormon.f90:18
CONDITION defines the physical condition of the agent
Definition: m_body.f90:29
REPRODUCTION type defines parameters of the reproduction system.
Definition: m_body.f90:252
Definition of a single food item. Food item is a spatial object that has specific location in space....
Definition: m_env.f90:371
This type adds hormonal architecture extending the genome object.
Definition: m_hormon.f90:28