ncompete.cpp 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. ///////////////////////////////////////////////////////////////////////////////////////
  2. /// \file ncompete.cpp
  3. /// \brief Distribution of N among individuals according to supply, demand and
  4. /// the individuals' uptake strength
  5. ///
  6. /// \author David Wårlind
  7. /// $Date: 2013-04-30 11:05:01 +0200 (Tue, 30 Apr 2013) $
  8. ///
  9. ///////////////////////////////////////////////////////////////////////////////////////
  10. #include "config.h"
  11. #include "ncompete.h"
  12. #include "guessmath.h"
  13. #include <assert.h>
  14. #include "driver.h"
  15. void ncompete(std::vector<NCompetingIndividual>& individuals, double nmass_avail) {
  16. double nsupply = nmass_avail; // Nitrogen available for uptake
  17. double total_ups = 0.0; // Total uptake strength
  18. // calculate total nitrogen uptake strength, and set all uptake to
  19. // zero initially
  20. for (size_t i = 0; i < individuals.size(); ++i) {
  21. total_ups += individuals[i].strength;
  22. individuals[i].fnuptake = 0;
  23. }
  24. bool full_uptake = true; // If an individual could get more than its demand, then
  25. // that indiv gets fnuptake = 1 and everything has to be
  26. // redone for all indiv with fnuptake < 1 as more nitrogen
  27. // could be taken up per unit strength (starts with true to
  28. // get into while loop)
  29. while (full_uptake) {
  30. full_uptake = false;
  31. double ratio_uptake; // Nitrogen per uptake strength
  32. // decide how much nitrogen that will be taken up by each uptake strength
  33. if (total_ups > 0.0) {
  34. ratio_uptake = nsupply / total_ups;
  35. }
  36. else {
  37. ratio_uptake = 0.0;
  38. }
  39. // Go through individuals
  40. for (size_t i = 0; i < individuals.size() && !full_uptake; ++i) {
  41. NCompetingIndividual& indiv = individuals[i];
  42. // if fnuptake doesn't meet indiv nitrogen demand, then calculate a new value for fnuptake
  43. if (indiv.fnuptake != 1.0) {
  44. // how much is the individual entitled to take up due to its strength?
  45. double entitlement = ratio_uptake * indiv.strength;
  46. // if indiv has the strength to take up more than its nitrogen demand
  47. if (entitlement > indiv.ndemand && !negligible(indiv.ndemand)) {
  48. indiv.fnuptake = 1.0;
  49. // nitrogen demand is subtract from nitrogen supply
  50. nsupply -= indiv.ndemand;
  51. // strength is subtracted from uptake strengths
  52. total_ups -= indiv.strength;
  53. // and redo indiv fnuptake calc for the rest of the indiv as this indiv probably could
  54. // take up more than its nitrogen demand -> more available for the rest of the indiv
  55. full_uptake = true;
  56. }
  57. // normal nitrogen limited uptake (0.0 < fnuptake < 1.0)
  58. else if (indiv.ndemand > 0.0) {
  59. indiv.fnuptake = min(1.0, entitlement / indiv.ndemand);
  60. }
  61. else {
  62. indiv.fnuptake = 0.0;
  63. }
  64. }
  65. }
  66. }
  67. }