spinupdata.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. ///////////////////////////////////////////////////////////////////////////////////////
  2. /// \file spinupdata.h
  3. /// \brief Management of climate data for spinup
  4. ///
  5. /// $Date: 2018-02-02 18:01:35 +0100 (ven, 02 fév 2018) $
  6. ///
  7. ///////////////////////////////////////////////////////////////////////////////////////
  8. #ifndef LPJ_GUESS_SPINUP_DATA_H
  9. #define LPJ_GUESS_SPINUP_DATA_H
  10. #include "guessmath.h"
  11. class Spinup_data {
  12. // Class for management of climate data for spinup
  13. // (derived from first few years of historical climate data)
  14. private:
  15. int nyear;
  16. int thisyear;
  17. double* data;
  18. bool havedata;
  19. // guess2008 - this array holds the climatology for the spinup period
  20. double dataclim[12];
  21. public:
  22. Spinup_data(int nyear_loc) {
  23. nyear=nyear_loc;
  24. havedata=false;
  25. data=new double[nyear*12];
  26. thisyear=0;
  27. havedata=true;
  28. reset_clim(); // guess2008
  29. }
  30. ~Spinup_data() {
  31. if (havedata) delete[] data;
  32. }
  33. double& operator[](int month) {
  34. return data[thisyear*12+month];
  35. }
  36. void nextyear() {
  37. if (thisyear==nyear-1) thisyear=0;
  38. else thisyear++;
  39. }
  40. void firstyear() {
  41. thisyear=0;
  42. }
  43. void get_data_from(double source[][12]) {
  44. int y,m;
  45. thisyear=0;
  46. for (y=0;y<nyear;y++) {
  47. for (m=0;m<12;m++) {
  48. data[y*12+m]=source[y][m];
  49. }
  50. }
  51. }
  52. // guess2008 - NEW METHODS
  53. void reset_clim() {
  54. for (int ii = 0; ii < 12; ii++) dataclim[ii] = 0.0;
  55. }
  56. void make_clim() {
  57. reset_clim(); // Always reset before calculating
  58. int y,m;
  59. for (y=0;y<nyear;y++) {
  60. for (m=0;m<12;m++) {
  61. dataclim[m] += data[y*12+m] / (double)nyear;
  62. }
  63. }
  64. }
  65. bool extract_data(double source[][12], const int& startyear, const int& endyear) {
  66. // Populate data with data from the middle of source.
  67. // Condition: endyear - startyear + 1 == nyear
  68. // if startyear == 1 and endyear == 30 then this function is identical to get_data_from above.
  69. if (endyear < startyear) return false;
  70. if (endyear - startyear + 1 == nyear) {
  71. int y,m;
  72. for (y=startyear-1;y<endyear;y++) {
  73. for (m=0;m<12;m++) {
  74. data[(y-(startyear-1))*12+m]=source[y][m];
  75. }
  76. }
  77. } else return false;
  78. return true;
  79. }
  80. void adjust_data(double anom[12], bool additive) {
  81. // Adjust the spinup data to the conditions prevailing at a particular time, as given by
  82. // the (additive or multiplicative) anomalies in anom
  83. int y,m;
  84. for (y=0;y<nyear;y++) {
  85. for (m=0;m<12;m++) {
  86. if (additive)
  87. data[y*12+m] += anom[m];
  88. else
  89. data[y*12+m] *= anom[m];
  90. }
  91. }
  92. }
  93. // Replace interannual data with the period's climatology.
  94. void use_clim_data() {
  95. int y,m;
  96. for (y=0;y<nyear;y++) {
  97. for (m=0;m<12;m++) {
  98. data[y*12+m] = dataclim[m];
  99. }
  100. }
  101. }
  102. // Alter variability about the mean climatology
  103. void adjust_data_variability(const double& factor) {
  104. // factor == 0 gives us the climatology (i.e. generalises use_clim_data above)
  105. // factor == 1 leaves everything unchanged
  106. // Remember to check the for negative precip or cloudiness values etc.
  107. // after calling this method.
  108. if (factor == 1.0) return;
  109. int y,m;
  110. for (y=0;y<nyear;y++) {
  111. for (m=0;m<12;m++) {
  112. data[y*12+m] = dataclim[m] + (data[y*12+m] - dataclim[m]) * factor;
  113. }
  114. }
  115. }
  116. void limit_data(double minval, double maxval) {
  117. // Limit data to a range
  118. int y,m;
  119. for (y=0;y<nyear;y++) {
  120. for (m=0;m<12;m++) {
  121. if (data[y*12+m] < minval) data[y*12+m] = minval;
  122. if (data[y*12+m] > maxval) data[y*12+m] = maxval;
  123. }
  124. }
  125. }
  126. void set_min_val(const double& oldval, const double& newval) {
  127. // Change values < oldval to newval
  128. int y,m;
  129. for (y=0;y<nyear;y++) {
  130. for (m=0;m<12;m++) {
  131. if (data[y*12+m] < oldval) data[y*12+m] = newval;
  132. }
  133. }
  134. }
  135. // guess2008 - END OF NEW METHODS
  136. void detrend_data(bool future = false) {
  137. int y,m;
  138. double a,b,anomaly;
  139. double* annual_mean=new double[nyear];
  140. double* year_number=new double[nyear];
  141. for (y=0;y<nyear;y++) {
  142. annual_mean[y]=0.0;
  143. for (m=0;m<12;m++) annual_mean[y]+=data[y*12+m];
  144. annual_mean[y]/=12.0;
  145. year_number[y]=y;
  146. }
  147. regress(year_number,annual_mean,nyear,a,b);
  148. for (y=0;y<nyear;y++) {
  149. if(future)
  150. anomaly = b * (double)(y - (nyear - 1));
  151. else
  152. anomaly=b*(double)y;
  153. for (m=0;m<12;m++)
  154. data[y*12+m]-=anomaly;
  155. }
  156. // guess2008 - added [] - Clean up
  157. delete[] annual_mean;
  158. delete[] year_number;
  159. }
  160. };
  161. /// Spinup data container supporting monthly, daily and sub-daily forcing
  162. /** Similar to Spinup_data, but forcing data can have 12, 365 or a multiple
  163. * of 365 values per year.
  164. *
  165. * There's no support for leap years, get rid of leap days before sending
  166. * the raw forcing data to this class.
  167. */
  168. class GenericSpinupData {
  169. public:
  170. static const int DAYS_PER_YEAR = 365;
  171. /// Datatype for the data, a 2D matrix of doubles
  172. typedef std::vector<std::vector<double> > RawData;
  173. GenericSpinupData();
  174. /// Loads the underlying forcing data (and sets the "current" year to 0)
  175. void get_data_from(RawData& source);
  176. /// Gets the value for a given timestep in the "current" year
  177. double operator[](int ts) const;
  178. /// Goes to the next year
  179. void nextyear();
  180. /// Goes to the first year
  181. void firstyear();
  182. /// Removes trend from the original data
  183. void detrend_data();
  184. /// Returns the number of years used to construct the spinup dataset
  185. size_t nbr_years() const;
  186. private:
  187. /// The "current" year
  188. int thisyear;
  189. /// The forcing data which is used over and over during the spinup
  190. RawData data;
  191. };
  192. #endif // LPJ_GUESS_SPINUP_DATA_H