PageRenderTime 64ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/container/ClassContainerBase.cxx

https://gitlab.com/ineris/GPEC
C++ | 2189 lines | 1722 code | 399 blank | 68 comment | 348 complexity | f811424b32b6a6b5187de0553fdbb5ee MD5 | raw file
Possible License(s): GPL-3.0
  1. // Copyright (C) 2013-2015 INERIS
  2. // Author(s) : Edouard Debry
  3. //
  4. // This file is part of GPEC.
  5. //
  6. // GPEC is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // GPEC is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with GPEC. If not, see <http://www.gnu.org/licenses/>.
  18. #ifndef GPEC_FILE_CLASS_CONTAINER_BASE_CXX
  19. #include "ClassContainerBase.hxx"
  20. namespace GPEC
  21. {
  22. // Set number of time steps.
  23. template<class T>
  24. inline void ClassContainerBase<T>::set_Nt()
  25. {
  26. Nt_ = 0;
  27. if (date_begin_ < date_end_)
  28. Nt_ = get_time_index(date_end_.GetSecondsFrom(date_begin_), delta_t_);
  29. }
  30. // Set number of days.
  31. template<class T>
  32. inline void ClassContainerBase<T>::set_Nd()
  33. {
  34. Nd_ = 0;
  35. if (date_begin_ < date_end_)
  36. Nd_ = date_end_.GetDaysFrom(date_begin_);
  37. if (Nd_ * Nt_day_ < Nt_)
  38. Nd_++;
  39. }
  40. // Get location index.
  41. template<class T>
  42. inline int ClassContainerBase<T>::get_location_index(const int &t, const int &location) const
  43. {
  44. if (data_(t).GetSize() == Nl_)
  45. return location;
  46. int l;
  47. for (l = 0; l < data_(t).GetSize(); l++)
  48. if (location_index_(t)(l) > location)
  49. return data_(t).GetSize();
  50. else if (location_index_(t)(l) == location)
  51. break;
  52. return l;
  53. }
  54. // Construct.
  55. template<class T>
  56. void ClassContainerBase<T>::construct(const string &prefix_base)
  57. {
  58. // Read configuration.
  59. Ops::Ops ops(this->configuration_file_);
  60. ops.SetPrefix("general.");
  61. delta_t_ = ops.Get<T>("Delta_t");
  62. // Custom values for species.
  63. value_min_ = ops.Get<T>(species_ + ".value_min", "", T(CONTAINER_VALUE_MIN));
  64. value_max_ = ops.Get<T>(species_ + ".value_max", "", T(CONTAINER_VALUE_MAX));
  65. // Set type and name of container.
  66. ops.SetPrefix(prefix_base);
  67. if (type_.empty())
  68. type_ = ops.Get<string>(name_ + ".type", "", name_);
  69. #ifdef GPEC_WITH_LOGGER
  70. if (! ops.Exists(type_))
  71. *(this->log_ptr_) << Warning() << "Container type \"" << type_
  72. << "\" not found in configuration file \"" << ClassGPEC::configuration_file_ << "\"." << endl;
  73. #endif
  74. // Set time step.
  75. ops.SetPrefix(prefix_base + type_ + ".");
  76. delta_t_ = ops.Get<T>("Delta_t", "", delta_t_);
  77. // If type appears to be already filtered.
  78. if (type_.substr(0, 4) == "peak" || type_.substr(0, 4) == "mean")
  79. delta_t_ = T(86400);
  80. if (delta_t_ > T(0))
  81. Nt_day_ = get_time_index<T>(T(86400), delta_t_);
  82. else
  83. throw GPEC::Error("Negative or null time step in configuration.");
  84. ops.Close();
  85. }
  86. // Init.
  87. template<class T>
  88. void ClassContainerBase<T>::Init()
  89. {
  90. Ops::Ops ops(ClassGPEC::configuration_file_);
  91. #ifdef GPEC_WITH_LOGGER
  92. *(ClassGPEC::log_ptr_) << Bgreen() << Fblack() << Info() << Reset()
  93. << "Init static data for base container class." << endl;
  94. #endif
  95. ops.SetPrefix("general.forecast.");
  96. forecast_min_ = ops.Get<int>("min");
  97. forecast_max_ = ops.Get<int>("max");
  98. #ifdef GPEC_WITH_LOGGER
  99. *(ClassGPEC::log_ptr_) << Fgreen() << Debug() << Reset() << "forecast_min = " << forecast_min_ << endl;
  100. *(ClassGPEC::log_ptr_) << Fgreen() << Debug() << Reset() << "forecast_max = " << forecast_max_ << endl;
  101. *(ClassGPEC::log_ptr_) << Bgreen() << Fblack() << User(0, "EXPLANATION") << Reset()
  102. << "Minimal and maximal forecast days used in GPEC : 0 means today, 1 tomorrow,"
  103. << " ..., and negative means an analysis, change with care." << endl;
  104. #endif
  105. ops.Close();
  106. }
  107. // Constructors.
  108. template<class T>
  109. ClassContainerBase<T>::ClassContainerBase()
  110. : ClassGPEC(), type_(""), name_(""), comment_(""),
  111. species_(""), date_begin_(DATE_END_DEFAULT), date_end_(DATE_BEGIN_DEFAULT), Nt_(0),
  112. Nt_day_(0), Nd_(0), delta_t_(T(0)), Nl_(0), value_min_(T(0)), value_max_(T(1.e9))
  113. {
  114. return;
  115. }
  116. template<class T>
  117. ClassContainerBase<T>::ClassContainerBase(const string &type,
  118. const string &name,
  119. const string &species,
  120. const string &prefix_base)
  121. : ClassGPEC(), type_(type), name_(name), comment_(""),
  122. species_(species), date_begin_(DATE_END_DEFAULT), date_end_(DATE_BEGIN_DEFAULT), Nt_(0),
  123. Nt_day_(0), Nd_(0), delta_t_(T(0)), Nl_(0), value_min_(T(0)), value_max_(T(1.e9))
  124. {
  125. construct(prefix_base);
  126. return;
  127. }
  128. template<class T>
  129. ClassContainerBase<T>::ClassContainerBase(const string &name,
  130. const string &species,
  131. const string &prefix_base)
  132. : ClassGPEC(), type_(""), name_(name), comment_(""),
  133. species_(species), date_begin_(DATE_END_DEFAULT), date_end_(DATE_BEGIN_DEFAULT), Nt_(0),
  134. Nt_day_(0), Nd_(0), delta_t_(T(0)), Nl_(0), value_min_(T(0)), value_max_(T(1.e9))
  135. {
  136. construct(prefix_base);
  137. return;
  138. }
  139. // Destructor.
  140. template<class T>
  141. ClassContainerBase<T>::~ClassContainerBase()
  142. {
  143. return;
  144. }
  145. // Clear data.
  146. template<class T>
  147. void ClassContainerBase<T>::Clear()
  148. {
  149. Nt_ = 0;
  150. Nd_ = 0;
  151. date_begin_.SetDate(DATE_END_DEFAULT);
  152. date_end_.SetDate(DATE_BEGIN_DEFAULT);
  153. forecast_.Clear();
  154. location_index_.Clear();
  155. data_.Clear();
  156. string comment = "cleared container";
  157. AddComment(comment);
  158. }
  159. template<class T>
  160. void ClassContainerBase<T>::PartialClear()
  161. {
  162. for (int t = 0; t < Nt_; t++)
  163. {
  164. location_index_(t).Clear();
  165. if (data_(t).GetSize() > 0)
  166. data_(t).Resize(1);
  167. }
  168. }
  169. // Copy constructor.
  170. template<class T>
  171. void ClassContainerBase<T>::Copy(const ClassContainerBase<T> &container, const string name)
  172. {
  173. // Name of copy may be different.
  174. name_ = name;
  175. // Everything else is identical.
  176. type_ = container.type_;
  177. species_ = container.species_;
  178. date_begin_ = container.date_begin_;
  179. date_end_ = container.date_end_;
  180. Nt_ = container.Nt_;
  181. Nd_ = container.Nd_;
  182. Nt_day_ = container.Nt_day_;
  183. delta_t_ = container.delta_t_;
  184. Nl_ = container.Nl_;
  185. location_index_ = container.location_index_;
  186. data_ = container.data_;
  187. forecast_ = container.forecast_;
  188. AddComment("copied from container \"" + container.name_ + "/" + container.type_ + "\"");
  189. ClassGPEC::Copy(container);
  190. }
  191. template<class T>
  192. bool ClassContainerBase<T>::HasSameStructure(const ClassContainerBase<T> &container) const
  193. {
  194. return Nl_ == container.Nl_;
  195. }
  196. // Checks if same time structure.
  197. template<class T>
  198. bool ClassContainerBase<T>::HasSameTimeStructure(const ClassContainerBase<T> &container) const
  199. {
  200. if (date_begin_ != container.date_begin_ ||
  201. Nt_ != container.Nt_ ||
  202. Nd_ != container.Nd_ ||
  203. Nt_day_ != container.Nt_day_)
  204. return false;
  205. return true;
  206. }
  207. template<class T>
  208. void ClassContainerBase<T>::SameTimeStructureAs(const ClassContainerBase<T> &container)
  209. {
  210. if (delta_t_ != container.delta_t_)
  211. throw GPEC::Error("Cannot put same time structure between containers with different time steps.");
  212. int t_beg(0), t_end(Nt_);
  213. if (date_begin_ < container.date_begin_)
  214. t_beg = GetDateIndex(container.date_begin_);
  215. if (date_end_ > container.date_end_)
  216. t_end = GetDateIndex(container.date_end_);
  217. RestrictDate(t_beg, t_end);
  218. Date date_beg(date_begin_), date_end(date_end_);
  219. if (date_begin_ > container.date_begin_)
  220. date_beg = container.date_begin_;
  221. if (date_end_ < container.date_end_)
  222. date_end = container.date_end_;
  223. ExtendDate(get_int_from_date(date_beg),
  224. get_int_from_date(date_end));
  225. }
  226. // Set methods.
  227. template<class T>
  228. void ClassContainerBase<T>::SetName(const string &name)
  229. {
  230. name_ = name;
  231. }
  232. template<class T>
  233. void ClassContainerBase<T>::SetType(const string &type)
  234. {
  235. type_ = type;
  236. }
  237. template<class T>
  238. void ClassContainerBase<T>::SetSpecies(const string &species)
  239. {
  240. species_ = species;
  241. }
  242. template<class T>
  243. void ClassContainerBase<T>::Set(const ClassContainerBase<T> &container, const string &prefix_base)
  244. {
  245. Clear();
  246. type_ = container.type_;
  247. name_ = container.name_;
  248. species_ = container.species_;
  249. construct(prefix_base);
  250. }
  251. template<class T> template<class U>
  252. void ClassContainerBase<T>::SetData(const Date &date_begin,
  253. const Date &date_end,
  254. const Vector1I &time,
  255. const Vector1I &location,
  256. const Vector1I &forecast,
  257. Vector<U> &data,
  258. const bool mask_negative_value)
  259. {
  260. if (data.GetSize() != time.GetSize() ||
  261. data.GetSize() != location.GetSize())
  262. throw GPEC::Error("Data vectors given in argument are not of equal size.");
  263. Clear();
  264. date_begin_ = date_begin;
  265. date_end_ = date_end;
  266. set_Nt();
  267. set_Nd();
  268. if (forecast.GetSize() != Nt_)
  269. throw GPEC::Error("Forecast vector should be of size " + to_str(Nt_) + ".");
  270. for (int i = 0; i < time.GetSize(); i++)
  271. check_index(0, Nt_, time(i));
  272. for (int i = 0; i < location.GetSize(); i++)
  273. check_index(0, Nl_, location(i));
  274. forecast_.Reallocate(Nt_);
  275. location_index_.Reallocate(Nt_);
  276. data_.Reallocate(Nt_);
  277. Vector1I Nl(Nt_);
  278. Nl.Zero();
  279. Vector<int> mask = check_data<U>(U(value_min_), U(value_max_), data);
  280. // Treat negative values as low values.
  281. if (! mask_negative_value)
  282. for (int i = 0; i < data.GetSize(); i++)
  283. if (mask(i) == -3)
  284. mask(i) = 1;
  285. // Negative values may appear for some sequential aggregation algorithms
  286. // that do not garantee positiveness. However, it usually appears because
  287. // of very low simulation values, and it should not be considered as an error.
  288. for (int i = 0; i < data.GetSize(); i++)
  289. if (mask(i) == 0)
  290. Nl(time(i))++;
  291. else
  292. {
  293. #ifdef GPEC_WITH_LOGGER
  294. *(this->log_ptr_) << User(0, "BAD-VALUE") << "At time " << time(i) << " and location "
  295. << location(i) << " got value " << data(i) << " ." << endl;
  296. #endif
  297. if (mask(i) > 0)
  298. {
  299. #ifdef GPEC_WITH_LOGGER
  300. *(this->log_ptr_) << User(0, "LOW-HIGH-VALUE") << "At time " << time(i) << " and location "
  301. << location(i) << " got value " << data(i) << " ." << endl;
  302. #endif
  303. Nl(time(i))++;
  304. data(i) = min<U>(max<U>(value_min_, data(i)), value_max_);
  305. }
  306. }
  307. for (int t = 0; t < Nt_; t++)
  308. if (Nl(t) > 0)
  309. {
  310. forecast_(t).Reallocate(1);
  311. check_index(forecast_min_, forecast_max_, forecast(t));
  312. forecast_(t)(0) = forecast(t);
  313. location_index_(t).Reallocate(Nl(t));
  314. data_(t).Reallocate(Nl(t));
  315. }
  316. Vector1I l(Nt_);
  317. l.Zero();
  318. for (int i = 0; i < data.GetSize(); i++)
  319. if (mask(i) >= 0)
  320. {
  321. int t = time(i);
  322. location_index_(t)(l(t)) = location(i);
  323. data_(t)(l(t)) = T(data(i));
  324. l(t)++;
  325. }
  326. for (int t = 0; t < Nt_; t++)
  327. for (int l = 1; l < location_index_(t).GetSize(); l++)
  328. if (location_index_(t)(l - 1) > location_index_(t)(l))
  329. {
  330. Sort(location_index_(t), data_(t));
  331. break;
  332. }
  333. // Location index not necessary if all locations are present.
  334. for (int t = 0; t < Nt_; t++)
  335. if (location_index_(t).GetSize() == Nl_)
  336. location_index_(t).Clear();
  337. }
  338. template<class T>
  339. void ClassContainerBase<T>::SetValueMin(const T &value_min)
  340. {
  341. value_min_ = value_min;
  342. }
  343. template<class T>
  344. void ClassContainerBase<T>::SetValueMax(const T &value_max)
  345. {
  346. value_max_ = value_max;
  347. }
  348. template<class T>
  349. void ClassContainerBase<T>::SetValue(const int &t,
  350. const int &location,
  351. const T &value)
  352. {
  353. if (value < value_min_ || value >= value_max_)
  354. return;
  355. check_index(0, Nt_, t);
  356. check_index(0, Nl_, location);
  357. int l = get_location_index(t, location);
  358. if (l < data_(t).GetSize())
  359. data_(t)(l) = value;
  360. }
  361. template<class T>
  362. void ClassContainerBase<T>::AddComment(const string add_comment)
  363. {
  364. comment_ += "At " + get_current_time() + ": " + add_comment + ".\n";
  365. }
  366. template<class T>
  367. void ClassContainerBase<T>::SetComment(const string &comment)
  368. {
  369. comment_ = comment;
  370. }
  371. // Check container.
  372. template<class T>
  373. void ClassContainerBase<T>::CheckContainer() const
  374. {
  375. if (Nt_ != location_index_.GetSize() ||
  376. Nt_ != data_.GetSize() ||
  377. Nt_ != forecast_.GetSize())
  378. throw GPEC::Error(string("Location index, forecast or data vector length does")
  379. + string(" not correspond to the number of time steps."));
  380. for (int t = 0; t < Nt_; t++)
  381. if (data_(t).GetSize() < Nl_)
  382. {
  383. if (location_index_(t).GetSize() != data_(t).GetSize())
  384. throw GPEC::Error("At time " + to_str(t) + ", sizes of location index and data vectors differ.");
  385. for (int l = 1; l < location_index_(t).GetSize(); l++)
  386. if (location_index_(t)(l - 1) >= location_index_(t)(l))
  387. throw GPEC::Error("At time " + to_str(t) + ", location indexes are not stored in ascending order.");
  388. }
  389. else if (data_(t).GetSize() == Nl_)
  390. {
  391. if (location_index_(t).GetSize() > 0)
  392. throw GPEC::Error("At time " + to_str(t) + ", location index vector should be empty.");
  393. }
  394. else
  395. throw GPEC::Error("At time " + to_str(t) + ", data vector greater than number of locations.");
  396. }
  397. // Find missing time steps.
  398. template<class T>
  399. void ClassContainerBase<T>::FindMissingTimeStep(Vector1I &missing_time_step) const
  400. {
  401. #ifdef GPEC_WITH_LOGGER
  402. *(this->log_ptr_) << Info() << "Looking for missing time steps ..." << endl;
  403. #endif
  404. for (int t = 0; t < Nt_; t++)
  405. if (data_(t).GetSize() == 0)
  406. missing_time_step.PushBack(t);
  407. #ifdef GPEC_WITH_LOGGER
  408. *(this->log_ptr_) << Info(1) << "... found " << missing_time_step.GetSize() << " of them." << endl;
  409. #endif
  410. }
  411. // Operations.
  412. template<class T>
  413. void ClassContainerBase<T>::Add(const T &value)
  414. {
  415. for (int t = 0; t < Nt_; t++)
  416. for (int l = 0; l < data_(t).GetSize(); l++)
  417. data_(t)(l) += value;
  418. }
  419. template<class T>
  420. void ClassContainerBase<T>::Mlt(const T &value)
  421. {
  422. for (int t = 0; t < Nt_; t++)
  423. for (int l = 0; l < data_(t).GetSize(); l++)
  424. data_(t)(l) *= value;
  425. }
  426. template<class T>
  427. void ClassContainerBase<T>::Set(const T &value)
  428. {
  429. for (int t = 0; t < Nt_; t++)
  430. for (int l = 0; l < data_(t).GetSize(); l++)
  431. data_(t)(l) = value;
  432. }
  433. // Print.
  434. template<class T>
  435. void ClassContainerBase<T>::Print(string &str, const bool &with_data) const
  436. {
  437. ostringstream sout;
  438. if (with_data)
  439. for (int t = 0; t < Nt_; t++)
  440. {
  441. Date date = date_begin_;
  442. date.AddSeconds(t * delta_t_);
  443. sout << setw(15) << left << date.GetDate("%y-%m-%d_%h");
  444. sout << setw(6) << left << "(" + to_str(t) + ")";
  445. Vector1T data;
  446. if (data_(t).GetSize() == Nl_)
  447. data = data_(t);
  448. else
  449. {
  450. data.Resize(Nl_);
  451. data.Fill(this->bad_value_);
  452. int loc(-1), l(0);
  453. while (++loc < Nl_ && l < location_index_(t).GetSize())
  454. if (location_index_(t)(l) == loc)
  455. data(loc) = data_(t)(l++);
  456. }
  457. for (int loc = 0; loc < Nl_; loc++)
  458. sout << setw(12) << setprecision(8) << left << data(loc);
  459. sout << endl;
  460. }
  461. for (int t = 0; t < Nt_; t++)
  462. {
  463. Date date = date_begin_;
  464. date.AddSeconds(t * delta_t_);
  465. sout << setw(15) << left << date.GetDate("%y-%m-%d_%h");
  466. sout << setw(8) << right << "(" + to_str(t) + ")";
  467. sout << setw(8) << right << data_(t).GetSize() << "/" << Nl_;
  468. if (forecast_(t).GetSize() > 0)
  469. sout << setw(4) << right << "D" << showpos << forecast_(t)(0);
  470. if (data_(t).GetSize() > 0)
  471. sout << setw(8) << right << noshowpos << fixed << setprecision(2) << Norm1(data_(t)) / T(data_(t).GetSize())
  472. << setw(8) << right << noshowpos << fixed << setprecision(2) << data_(t).GetNormInf();
  473. sout << endl;
  474. }
  475. sout << "Container: " << name_ << "/" << type_ << endl
  476. << "Species: " << this->species_ << endl;
  477. sout << "Date: " << date_begin_.GetDate("%y-%m-%d_%h") << " ---> "
  478. << date_end_.GetDate("%y-%m-%d_%h") << " (excluded)" << endl
  479. << "Time step = " << setprecision(1) << fixed << delta_t_ << " seconds" << endl
  480. << "Number of time steps = " << Nt_ << endl
  481. << "Number of days = " << Nd_ << endl;
  482. if (! comment_.empty())
  483. {
  484. sout << "Comment:" << endl;
  485. vector<string> ls = split(comment_, "\n");
  486. for (int i = 0; i < int(ls.size()); i++)
  487. sout << " " << ls[i] << endl;
  488. }
  489. str = sout.str();
  490. }
  491. // Get methods.
  492. template<class T>
  493. string ClassContainerBase<T>::GetType() const
  494. {
  495. return type_;
  496. }
  497. template<class T>
  498. string ClassContainerBase<T>::GetName() const
  499. {
  500. return name_;
  501. }
  502. template<class T>
  503. string ClassContainerBase<T>::GetComment() const
  504. {
  505. return comment_;
  506. }
  507. template<class T>
  508. string ClassContainerBase<T>::GetSpecies() const
  509. {
  510. return species_;
  511. }
  512. template<class T>
  513. int ClassContainerBase<T>::GetLocationIndex(const int &t, const int &location) const
  514. {
  515. return get_location_index(t, location);
  516. }
  517. template<class T>
  518. inline int ClassContainerBase<T>::GetNlTotal() const
  519. {
  520. int NlTotal(0);
  521. for (int t = 0; t < data_.GetSize(); t++)
  522. NlTotal += data_(t).GetSize();
  523. return NlTotal;
  524. }
  525. template<class T>
  526. int ClassContainerBase<T>::GetNl(const int &t) const
  527. {
  528. return data_(t).GetSize();
  529. }
  530. template<class T>
  531. int ClassContainerBase<T>::GetNlocation() const
  532. {
  533. return Nl_;
  534. }
  535. template<class T>
  536. int ClassContainerBase<T>::GetNt() const
  537. {
  538. return Nt_;
  539. }
  540. template<class T>
  541. int ClassContainerBase<T>::GetNtDay() const
  542. {
  543. return Nt_day_;
  544. }
  545. template<class T>
  546. int ClassContainerBase<T>::GetNd() const
  547. {
  548. return Nd_;
  549. }
  550. template<class T>
  551. T ClassContainerBase<T>::GetDeltat() const
  552. {
  553. return delta_t_;
  554. }
  555. template<class T>
  556. int ClassContainerBase<T>::GetDateIndex(const Date &date) const
  557. {
  558. return get_time_index<T>(date.GetSecondsFrom(date_begin_), delta_t_);
  559. }
  560. template<class T>
  561. Date ClassContainerBase<T>::GetDate(const int &t) const
  562. {
  563. Date date(date_begin_);
  564. date.AddSeconds(t * delta_t_);
  565. return date;
  566. }
  567. template<class T>
  568. Date ClassContainerBase<T>::GetDateBegin() const
  569. {
  570. return date_begin_;
  571. }
  572. template<class T>
  573. Date ClassContainerBase<T>::GetDateEnd() const
  574. {
  575. return date_end_;
  576. }
  577. template<class T>
  578. string ClassContainerBase<T>::GetDateStr(const int &t,
  579. const string format) const
  580. {
  581. return GetDate(t).GetDate(format);
  582. }
  583. template<class T>
  584. int ClassContainerBase<T>::GetDateIndexStr(const string &date_str) const
  585. {
  586. Date date(date_str);
  587. return GetDateIndex(date);
  588. }
  589. template<class T>
  590. string ClassContainerBase<T>::GetDateBeginStr(const string format) const
  591. {
  592. return date_begin_.GetDate(format);
  593. }
  594. template<class T>
  595. string ClassContainerBase<T>::GetDateEndStr(const string format) const
  596. {
  597. return date_end_.GetDate(format);
  598. }
  599. template<class T>
  600. T ClassContainerBase<T>::GetValue(const int &t, const int &location) const
  601. {
  602. check_index(0, Nt_, t);
  603. check_index(0, Nl_, location);
  604. int l = get_location_index(t, location);
  605. if (l < data_(t).GetSize())
  606. return data_(t)(l);
  607. else
  608. return this->bad_value_;
  609. }
  610. template<class T>
  611. inline T ClassContainerBase<T>::GetValueRaw(const int &t, const int &l) const
  612. {
  613. return data_(t)(l);
  614. }
  615. template<class T>
  616. int ClassContainerBase<T>::GetForecastDay(const int &t) const
  617. {
  618. check_index(0, Nt_, t);
  619. if (forecast_(t).GetSize() > 0)
  620. return forecast_(t)(0);
  621. else
  622. return int(this->bad_value_);
  623. }
  624. template<class T>
  625. T ClassContainerBase<T>::GetForecastDayMean(int t_begin, int t_end) const
  626. {
  627. if (t_end == 0)
  628. t_end = Nt_;
  629. int sum(0), count(0);
  630. for (int t = t_begin; t < t_end; t++)
  631. if (forecast_(t).GetSize() > 0)
  632. {
  633. sum += forecast_(t)(0);
  634. count++;
  635. }
  636. if (count > 0)
  637. return T(sum) / T(count);
  638. else
  639. return this->bad_value_;
  640. }
  641. template<class T>
  642. inline void ClassContainerBase<T>::CollectData(Vector1I &time,
  643. Vector1I& location,
  644. Vector1T &data) const
  645. {
  646. int Nsize(Nt_ * Nl_);
  647. time.Reallocate(Nsize);
  648. location.Reallocate(Nsize);
  649. data.Reallocate(Nsize);
  650. int i(0);
  651. for (int t = 0; t < Nt_; t++)
  652. if (data_(t).GetSize() == Nl_)
  653. for (int l = 0; l < Nl_; l++)
  654. {
  655. time(i) = t;
  656. location(i) = l;
  657. data(i++) = data_(t)(l);
  658. }
  659. else
  660. for (int l = 0; l < data_(t).GetSize(); l++)
  661. {
  662. time(i) = t;
  663. location(i) = location_index_(t)(l);
  664. data(i++) = data_(t)(l);
  665. }
  666. time.Resize(i);
  667. location.Resize(i);
  668. data.Resize(i);
  669. }
  670. template<class T>
  671. inline void ClassContainerBase<T>::CollectDataPeriod(const int &t_begin,
  672. const int &t_end,
  673. Vector1I &time,
  674. Vector1I& location,
  675. Vector1T &data) const
  676. {
  677. time.Clear();
  678. location.Clear();
  679. data.Clear();
  680. check_index(0, Nt_, t_begin);
  681. check_index(t_begin + 1, Nt_ + 1, t_end);
  682. int Nsize((t_end - t_begin) * Nl_);
  683. time.Reallocate(Nsize);
  684. location.Reallocate(Nsize);
  685. data.Reallocate(Nsize);
  686. int i(0);
  687. for (int t = t_begin; t < t_end; t++)
  688. if (data_(t).GetSize() == Nl_)
  689. for (int l = 0; l < data_(t).GetSize(); l++)
  690. {
  691. time(i) = t;
  692. location(i) = l;
  693. data(i++) = data_(t)(l);
  694. }
  695. else
  696. for (int l = 0; l < data_(t).GetSize(); l++)
  697. {
  698. time(i) = t;
  699. location(i) = location_index_(t)(l);
  700. data(i++) = data_(t)(l);
  701. }
  702. time.Resize(i);
  703. location.Resize(i);
  704. data.Resize(i);
  705. }
  706. template<class T>
  707. inline void ClassContainerBase<T>::CollectDataLocation(const int &location,
  708. Vector1I &time,
  709. Vector1T &data) const
  710. {
  711. time.Clear();
  712. data.Clear();
  713. check_index(0, Nl_, location);
  714. time.Reallocate(Nt_);
  715. data.Reallocate(Nt_);
  716. int i(0);
  717. for (int t = 0; t < Nt_; t++)
  718. {
  719. int l = get_location_index(t, location);
  720. if (l < data_(t).GetSize())
  721. {
  722. time(i) = t;
  723. data(i++) = data_(t)(l);
  724. }
  725. }
  726. time.Resize(i);
  727. data.Resize(i);
  728. }
  729. template<class T>
  730. inline void ClassContainerBase<T>::CollectDataTime(const int &t,
  731. Vector1I &location,
  732. Vector1T &data) const
  733. {
  734. location.Clear();
  735. data.Clear();
  736. if (data_(t).GetSize() == Nl_)
  737. {
  738. location.Reallocate(Nl_);
  739. location.Fill();
  740. }
  741. else
  742. location = location_index_(t);
  743. data = data_(t);
  744. }
  745. template<class T>
  746. inline void ClassContainerBase<T>::CollectDataTimeAtLocation(const int &t,
  747. const Vector1I &location,
  748. Vector1I &location_index,
  749. Vector1T &data) const
  750. {
  751. location_index.Reallocate(location.GetSize());
  752. data.Reallocate(location.GetSize());
  753. int j(0);
  754. if (data_(t).GetSize() == Nl_)
  755. for (int i = 0; i < location.GetSize(); i++)
  756. {
  757. location_index(j) = location(i);
  758. data(j++) = data_(t)(location(i));
  759. }
  760. else
  761. {
  762. int i(0), l(0);
  763. while (l < location_index_(t).GetSize() && i < location.GetSize())
  764. if (location_index_(t)(l) > location(i))
  765. i++;
  766. else if (location_index_(t)(l) < location(i))
  767. l++;
  768. else
  769. {
  770. location_index(j) = location(i);
  771. data(j++) = data_(t)(l);
  772. i++;
  773. l++;
  774. }
  775. }
  776. location_index.Resize(j);
  777. data.Resize(j);
  778. }
  779. template<class T>
  780. void ClassContainerBase<T>::CollectDataRaw(Vector1T &data,
  781. const bool with_bad_value) const
  782. {
  783. Vector1I time, location;
  784. Vector1T data_tmp;
  785. CollectData(time, location, data_tmp);
  786. if (with_bad_value)
  787. {
  788. data.Reallocate(Nt_ * Nl_);
  789. data.Fill(this->bad_value_);
  790. for (int i = 0; i < data_tmp.GetSize(); i++)
  791. data(Nl_ * time(i) + location(i)) = data_tmp(i);
  792. }
  793. else
  794. data = data_tmp;
  795. }
  796. template<class T>
  797. void ClassContainerBase<T>::CollectDataLocationRaw(const int &location,
  798. Vector1T &data,
  799. const bool with_bad_value) const
  800. {
  801. Vector1I time;
  802. Vector1T data_tmp;
  803. CollectDataLocation(location, time, data_tmp);
  804. if (with_bad_value)
  805. {
  806. data.Reallocate(Nt_);
  807. data.Fill(this->bad_value_);
  808. for (int i = 0; i < data_tmp.GetSize(); i++)
  809. data(time(i)) = data_tmp(i);
  810. }
  811. else
  812. data = data_tmp;
  813. }
  814. template<class T>
  815. void ClassContainerBase<T>::CollectDataTimeRaw(const int &t,
  816. Vector1T &data,
  817. const bool with_bad_value) const
  818. {
  819. Vector1I location;
  820. Vector1T data_tmp;
  821. CollectDataTime(t, location, data_tmp);
  822. if (with_bad_value)
  823. {
  824. data.Reallocate(Nl_);
  825. data.Fill(this->bad_value_);
  826. for (int i = 0; i < data_tmp.GetSize(); i++)
  827. data(location(i)) = data_tmp(i);
  828. }
  829. else
  830. data = data_tmp;
  831. }
  832. template<class T>
  833. void ClassContainerBase<T>::CollectDataPeriodRaw(const int &t_begin,
  834. const int &t_end,
  835. Vector1T &data,
  836. const bool with_bad_value) const
  837. {
  838. Vector1I time, location;
  839. Vector1T data_tmp;
  840. CollectDataPeriod(t_begin, t_end, time, location, data_tmp);
  841. if (with_bad_value)
  842. {
  843. data.Reallocate((t_end - t_begin) * Nl_);
  844. data.Fill(this->bad_value_);
  845. for (int i = 0; i < data_tmp.GetSize(); i++)
  846. data(Nl_ * (time(i) - t_begin) + location(i)) = data_tmp(i);
  847. }
  848. else
  849. data = data_tmp;
  850. }
  851. // Remove or keep locations.
  852. template<class T>
  853. void ClassContainerBase<T>::RemoveTimeStep(const Vector1I &time_step)
  854. {
  855. // Abruptly remove some time steps.
  856. for (int i = 0; i < time_step.GetSize(); i++)
  857. {
  858. int t = time_step(i);
  859. forecast_(t).Clear();
  860. location_index_(t).Clear();
  861. data_(t).Clear();
  862. }
  863. }
  864. template<class T>
  865. void ClassContainerBase<T>::RemoveLocation(const Vector1I &location)
  866. {
  867. Vector1I location_ascending = location;
  868. Sort(location_ascending);
  869. Vector1I location_keep(Nl_);
  870. int l(-1), i(0), j(0);
  871. while (++l < Nl_)
  872. if (i < location_ascending.GetSize())
  873. {
  874. if (l == location_ascending(i))
  875. i++;
  876. else
  877. location_keep(j++) = l;
  878. }
  879. else
  880. location_keep(j++) = l;
  881. location_keep.Resize(j);
  882. KeepLocation(location_keep);
  883. }
  884. template<class T>
  885. void ClassContainerBase<T>::KeepLocation(const Vector1I &location)
  886. {
  887. Vector1I location_ascending = location;
  888. Sort(location_ascending);
  889. for (int t = 0; t < Nt_; t++)
  890. {
  891. Vector1I location_index_new(data_(t).GetSize());
  892. Vector1T data_new(data_(t).GetSize());
  893. int i(0), count(0);
  894. if (data_(t).GetSize() == Nl_)
  895. {
  896. int l(-1);
  897. while (++l < Nl_ && i < location_ascending.GetSize())
  898. if (l == location_ascending(i))
  899. {
  900. location_index_new(count) = l;
  901. data_new(count++) = data_(t)(l);
  902. i++;
  903. }
  904. }
  905. else
  906. {
  907. int l(0);
  908. while (l < location_index_(t).GetSize() && i < location_ascending.GetSize())
  909. if (location_index_(t)(l) > location_ascending(i))
  910. i++;
  911. else if (location_index_(t)(l) < location_ascending(i))
  912. l++;
  913. else
  914. {
  915. location_index_new(count) = location_index_(t)(l);
  916. data_new(count++) = data_(t)(l);
  917. l++;
  918. i++;
  919. }
  920. }
  921. location_index_new.Resize(count);
  922. data_new.Resize(count);
  923. if (count == 0)
  924. forecast_(t).Clear();
  925. location_index_(t) = location_index_new;
  926. data_(t) = data_new;
  927. }
  928. AddComment("kept " + to_str(location.GetSize()) + " locations");
  929. }
  930. // Restrict or extend date range.
  931. template<class T>
  932. void ClassContainerBase<T>::RestrictDate(const int &t_begin, const int &t_end)
  933. {
  934. check_index(0, Nt_, t_begin);
  935. check_index(t_begin + 1, Nt_ + 1, t_end);
  936. Nt_ = t_end - t_begin;
  937. date_begin_.AddSeconds(t_begin * delta_t_);
  938. date_end_ = date_begin_;
  939. date_end_.AddSeconds(Nt_ * delta_t_);
  940. set_Nd();
  941. for (int t = 0; t < Nt_; t++)
  942. {
  943. int t_offset(t_begin + t);
  944. forecast_(t) = forecast_(t_offset);
  945. location_index_(t) = location_index_(t_offset);
  946. data_(t) = data_(t_offset);
  947. }
  948. forecast_.Resize(Nt_);
  949. location_index_.Resize(Nt_);
  950. data_.Resize(Nt_);
  951. AddComment("restricted container between time steps " + to_str(t_begin)
  952. + " and " + to_str(t_end) + " (excluded)");
  953. }
  954. template<class T>
  955. void ClassContainerBase<T>::ExtendDate(const int &date_begin_int, const int &date_end_int)
  956. {
  957. Date date_begin_ext = get_date_from_int(date_begin_int);
  958. Date date_end_ext = get_date_from_int(date_end_int);
  959. if (date_begin_ext > date_begin_ && date_end_ext <= date_end_)
  960. return;
  961. int t_old = get_time_index<T>(date_begin_.GetSecondsFrom(date_begin_ext), delta_t_);
  962. int Nt_old(Nt_);
  963. date_begin_ = date_begin_ext;
  964. date_end_ = date_end_ext;
  965. set_Nt();
  966. set_Nd();
  967. forecast_.Resize(Nt_);
  968. location_index_.Resize(Nt_);
  969. data_.Resize(Nt_);
  970. if (t_old != 0)
  971. for (int t = Nt_old - 1; t >= 0; t--)
  972. {
  973. int t_new(t + t_old);
  974. forecast_(t_new) = forecast_(t);
  975. location_index_(t_new) = location_index_(t);
  976. data_(t_new) = data_(t);
  977. forecast_(t).Clear();
  978. location_index_(t).Clear();
  979. data_(t).Clear();
  980. }
  981. AddComment("extended container between dates " + date_begin_ext.GetDate("%y-%m-%d_%h")
  982. + " and " + date_end_ext.GetDate("%y-%m-%d_%h") + " (excluded)");
  983. }
  984. // Merge.
  985. template<class T>
  986. void ClassContainerBase<T>::Merge(const ClassContainerBase<T> &container,
  987. const bool overwrite)
  988. {
  989. if (delta_t_ != container.delta_t_)
  990. throw GPEC::Error("Not equal time step between containers.");
  991. if (Nl_ != container.Nl_)
  992. throw GPEC::Error("Not equal number of locations between containers.");
  993. Date date_begin_merge = min<Date>(date_begin_, container.date_begin_);
  994. Date date_end_merge = max<Date>(date_end_, container.date_end_);
  995. // Extend current container to merge dates.
  996. ExtendDate(get_int_from_date(date_begin_merge),
  997. get_int_from_date(date_end_merge));
  998. // Merge with other container.
  999. int t_merge(0);
  1000. Date date_running(date_begin_merge);
  1001. while (date_running < date_end_merge)
  1002. {
  1003. if (date_running >= container.date_begin_ &&
  1004. date_running < container.date_end_)
  1005. {
  1006. int t = container.GetDateIndex(date_running);
  1007. if (data_(t_merge).GetSize() == 0)
  1008. {
  1009. forecast_(t_merge) = container.forecast_(t);
  1010. location_index_(t_merge) = container.location_index_(t);
  1011. data_(t_merge) = container.data_(t);
  1012. }
  1013. else
  1014. {
  1015. int l(0), l_merge(0), count(0);
  1016. if (container.data_(t).GetSize() == Nl_ && data_(t_merge).GetSize() == Nl_ && overwrite)
  1017. {
  1018. data_(t_merge) = container.data_(t);
  1019. count = Nl_;
  1020. }
  1021. else if (container.data_(t).GetSize() == Nl_)
  1022. {
  1023. while (l < Nl_ && l_merge < location_index_(t_merge).GetSize())
  1024. if (l < location_index_(t_merge)(l_merge))
  1025. {
  1026. location_index_(t_merge).PushBack(l);
  1027. data_(t_merge).PushBack(container.data_(t)(l));
  1028. l++;
  1029. count++;
  1030. }
  1031. else if (l == location_index_(t_merge)(l_merge))
  1032. {
  1033. if (overwrite)
  1034. {
  1035. data_(t_merge)(l_merge) = container.data_(t)(l);
  1036. count++;
  1037. }
  1038. l++;
  1039. l_merge++;
  1040. }
  1041. }
  1042. else if (data_(t_merge).GetSize() == Nl_ && overwrite)
  1043. {
  1044. for (l = 0; l < container.data_(t).GetSize(); l++)
  1045. data_(t)(container.location_index_(t)(l)) = container.data_(t)(l);
  1046. count = container.data_(t).GetSize();
  1047. }
  1048. else
  1049. {
  1050. while (l < container.location_index_(t).GetSize() &&
  1051. l_merge < location_index_(t_merge).GetSize())
  1052. if (container.location_index_(t)(l) > location_index_(t_merge)(l_merge))
  1053. l_merge++;
  1054. else if (container.location_index_(t)(l) < location_index_(t_merge)(l_merge))
  1055. {
  1056. location_index_(t_merge).PushBack(container.location_index_(t)(l));
  1057. data_(t_merge).PushBack(container.data_(t)(l));
  1058. l++;
  1059. count++;
  1060. }
  1061. else
  1062. {
  1063. if (overwrite)
  1064. {
  1065. data_(t_merge)(l_merge) = container.data_(t)(l);
  1066. count++;
  1067. }
  1068. l++;
  1069. l_merge++;
  1070. }
  1071. }
  1072. if (count > 0)
  1073. forecast_(t_merge).PushBack(container.forecast_(t)(0));
  1074. }
  1075. if (data_(t_merge).GetSize() > 0)
  1076. for (int l = 1; l < location_index_(t_merge).GetSize(); l++)
  1077. if (location_index_(t_merge)(l - 1) > location_index_(t_merge)(l))
  1078. {
  1079. Sort(location_index_(t_merge), data_(t_merge));
  1080. break;
  1081. }
  1082. }
  1083. t_merge++;
  1084. date_running.AddSeconds(delta_t_);
  1085. }
  1086. string add_comment = "merged with container \"" + container.name_ + "/" + container.type_ + "\"";
  1087. if (overwrite)
  1088. add_comment += ", with option overwrite";
  1089. AddComment(add_comment);
  1090. }
  1091. // Filter data.
  1092. template<class T> template<class F>
  1093. void ClassContainerBase<T>::FilterTime(const int h_frequency, const int h_offset,
  1094. string prefix_type,
  1095. const int h_begin, int h_end, const T ratio)
  1096. {
  1097. if (h_frequency == 1)
  1098. return;
  1099. if (abs(h_offset) >= h_frequency)
  1100. throw GPEC::Error("The absolute offset filter cannot equal or exceed the filter frequency.");
  1101. // Only relevant if data frequency is less than daily.
  1102. T delta_t_new = h_frequency * delta_t_;
  1103. if (delta_t_new > T(86400))
  1104. throw GPEC::Error("In GPEC, the time step cannot exceed one day.");
  1105. if (h_end == 0)
  1106. h_end = h_frequency;
  1107. int count_min = int(ratio * h_frequency);
  1108. int t_begin(0), t_end(Nt_);
  1109. int Nt_new = int((Nt_ - h_offset) / h_frequency + 1.e-5);
  1110. if ((Nt_ - h_offset) % h_frequency > count_min)
  1111. Nt_new++;
  1112. else
  1113. t_end -= (Nt_ - h_offset) % h_frequency;
  1114. date_begin_.AddSeconds((h_frequency / 2 + h_offset) * delta_t_);
  1115. if (h_offset > 0)
  1116. t_begin = h_offset;
  1117. else if (h_offset < 0)
  1118. if ((h_frequency + h_offset) < count_min)
  1119. {
  1120. Nt_new--;
  1121. t_begin = h_frequency + h_offset;
  1122. date_begin_.AddSeconds(h_frequency * delta_t_ );
  1123. }
  1124. Vector2I forecast_new(Nt_new);
  1125. Vector2I location_index_new(Nt_new);
  1126. Vector2T data_new(Nt_new);
  1127. for (int t = 0; t < Nt_new; t++)
  1128. {
  1129. forecast_new(t).Reallocate(1);
  1130. location_index_new(t).Reallocate(Nl_);
  1131. data_new(t).Reallocate(Nl_);
  1132. }
  1133. Vector1I index(Nt_new);
  1134. index.Zero();
  1135. F filter;
  1136. for (int location = 0; location < Nl_; location++)
  1137. {
  1138. Vector1I forecast_frequency(Nt_new);
  1139. forecast_frequency.Zero();
  1140. Vector1T data_frequency(Nt_new);
  1141. data_frequency.Fill(filter.Begin());
  1142. Vector1I count(Nt_new);
  1143. count.Zero();
  1144. int h(0), h_count(0);
  1145. for (int t = t_begin; t < t_end; t++)
  1146. {
  1147. int l = get_location_index(t, location);
  1148. if (l < data_(t).GetSize())
  1149. if (h_count >= h_begin)
  1150. if (h_count < h_end)
  1151. {
  1152. forecast_frequency(h) += forecast_(t)(0);
  1153. filter.Do(data_(t)(l), data_frequency(h));
  1154. count(h)++;
  1155. }
  1156. h_count++;
  1157. if (h_count == h_frequency)
  1158. {
  1159. h++;
  1160. h_count = 0;
  1161. }
  1162. }
  1163. for (int h = 0; h < Nt_new; h++)
  1164. if (count(h) > count_min)
  1165. {
  1166. forecast_new(h)(0) = int(rint(T(forecast_frequency(h)) / T(count(h))));
  1167. location_index_new(h)(index(h)) = location;
  1168. data_new(h)(index(h)) = filter.End(count(h), data_frequency(h));
  1169. index(h)++;
  1170. }
  1171. }
  1172. for (int t = 0; t < Nt_new; t++)
  1173. {
  1174. if (index(t) == 0)
  1175. forecast_new(t).Clear();
  1176. if (index(t) == Nl_)
  1177. location_index_new(t).Clear();
  1178. else
  1179. location_index_new(t).Resize(index(t));
  1180. data_new(t).Resize(index(t));
  1181. }
  1182. // Update attributes.
  1183. date_end_ = date_begin_;
  1184. date_end_.AddSeconds(Nt_new * delta_t_new);
  1185. Nt_ = Nt_new;
  1186. delta_t_ = delta_t_new;
  1187. set_Nd();
  1188. Nt_day_ = int(T(86400) / delta_t_);
  1189. forecast_ = forecast_new;
  1190. location_index_ = location_index_new;
  1191. data_ = data_new;
  1192. AddComment("filtered " + filter.Name() + " with frequency " + to_str(h_frequency)
  1193. + " and offset " + to_str(h_offset) + ", between " + to_str(h_begin) + " and " + to_str(h_end));
  1194. // Prefix type with something to say we filtered time.
  1195. if (prefix_type.empty())
  1196. {
  1197. prefix_type = filter.Name();
  1198. if (h_frequency < 24)
  1199. prefix_type += to_str(h_frequency);
  1200. }
  1201. if (prefix_type != "-")
  1202. type_ = prefix_type + type_;
  1203. }
  1204. // Filter time steps with two few data.
  1205. template<class T>
  1206. void ClassContainerBase<T>::FilterTimeStep(const int location_min)
  1207. {
  1208. #ifdef GPEC_WITH_LOGGER
  1209. *(this->log_ptr_) << Info() << "Filter time steps with"
  1210. << " number of locations < " << location_min << endl;
  1211. #endif
  1212. int count_filtered(0);
  1213. for (int t = 0; t < Nt_; t++)
  1214. if (data_(t).GetSize() < location_min)
  1215. {
  1216. count_filtered++;
  1217. #ifdef GPEC_WITH_LOGGER
  1218. *(this->log_ptr_) << Debug(2) << "Filter time step "
  1219. << t << " with number of locations = "
  1220. << data_(t).GetSize() << endl;
  1221. #endif
  1222. location_index_(t).Clear();
  1223. data_(t).Clear();
  1224. forecast_(t).Clear();
  1225. }
  1226. #ifdef GPEC_WITH_LOGGER
  1227. *(this->log_ptr_) << Debug(1) << "Filtered "
  1228. << count_filtered << " time steps." << endl;
  1229. #endif
  1230. AddComment("filtered " + to_str(count_filtered) + " time steps");
  1231. }
  1232. // Filter value.
  1233. template<class T>
  1234. void ClassContainerBase<T>::FilterValue(T value_min, T value_max,
  1235. const bool keep_threshold)
  1236. {
  1237. value_min = value_min == T(0) ? value_min_ : value_min;
  1238. value_max = value_max == T(1e9) ? value_max_ : value_max;
  1239. if (value_min < value_min_ || value_max > value_max_)
  1240. return;
  1241. #ifdef GPEC_WITH_LOGGER
  1242. *(this->log_ptr_) << Debug() << "Filter values below "
  1243. << value_min << " and above " << value_max
  1244. << ", filtered values are "
  1245. << (keep_threshold ? "REPLACED by min or max" : "REMOVED")
  1246. << endl;
  1247. #endif
  1248. int count_filtered(0);
  1249. for (int t = 0; t < Nt_; t++)
  1250. {
  1251. int Nl = data_(t).GetSize();
  1252. int i(0);
  1253. if (Nl > 0)
  1254. {
  1255. if (location_index_(t).GetSize() == 0)
  1256. {
  1257. location_index_(t).Reallocate(Nl);
  1258. location_index_(t).Fill();
  1259. }
  1260. for (int l = 0; l < Nl; l++)
  1261. if (data_(t)(l) < value_min)
  1262. {
  1263. count_filtered++;
  1264. #ifdef GPEC_WITH_LOGGER
  1265. *(this->log_ptr_) << Debug(2) << "Filter value "
  1266. << setprecision(2) << fixed << data_(t)(l) << " at location "
  1267. << l << " and time " << t << endl;
  1268. #endif
  1269. if (keep_threshold)
  1270. {
  1271. location_index_(t)(i) = location_index_(t)(l);
  1272. data_(t)(i++) = value_min;
  1273. }
  1274. }
  1275. else if (data_(t)(l) > value_max)
  1276. {
  1277. count_filtered++;
  1278. #ifdef GPEC_WITH_LOGGER
  1279. *(this->log_ptr_) << Debug(2) << "Filter value "
  1280. << setprecision(2) << fixed << data_(t)(l) << " at location "
  1281. << l << " and time " << t << endl;
  1282. #endif
  1283. if (keep_threshold)
  1284. {
  1285. location_index_(t)(i) = location_index_(t)(l);
  1286. data_(t)(i++) = value_max;
  1287. }
  1288. }
  1289. else
  1290. {
  1291. location_index_(t)(i) = location_index_(t)(l);
  1292. data_(t)(i++) = data_(t)(l);
  1293. }
  1294. location_index_(t).Resize(i);
  1295. data_(t).Resize(i);
  1296. if (data_(t).GetSize() == 0)
  1297. forecast_(t).Clear();
  1298. if (data_(t).GetSize() == Nl_)
  1299. location_index_(t).Clear();
  1300. }
  1301. }
  1302. #ifdef GPEC_WITH_LOGGER
  1303. *(this->log_ptr_) << Debug(1) << "Filtered "
  1304. << count_filtered << " values." << endl;
  1305. #endif
  1306. AddComment("filtered " + to_str(count_filtered) + " values below "
  1307. + to_str(value_min) + " and above " + to_str(value_max));
  1308. }
  1309. // Filter values below or above given multiple of standard deviation.
  1310. template<class T>
  1311. void ClassContainerBase<T>::FilterStandardDeviation(const T multiple_std,
  1312. const int location_min,
  1313. int t_begin, int t_end,
  1314. const bool keep_threshold)
  1315. {
  1316. if (multiple_std <= T(0))
  1317. throw GPEC::Error("Standard deviation multiple should be strictly positive");
  1318. check_index(0, Nt_, t_begin);
  1319. t_end = t_end == 0 ? Nt_ : t_end;
  1320. #ifdef GPEC_WITH_LOGGER
  1321. *(this->log_ptr_) << Info() << "Filter values with "
  1322. << multiple_std << " x standard deviation between timesteps ["
  1323. << t_begin << ", " << t_end << "[" << endl;
  1324. #endif
  1325. int count_filtered(0);
  1326. // At each time step, compute the mean and standard deviation value
  1327. // and remove values which are superior or inferior to mean +- std * multiple_std.
  1328. for (int t = t_begin; t < t_end; t++)
  1329. if (data_(t).GetSize() > location_min)
  1330. {
  1331. int Nl = data_(t).GetSize();
  1332. // Compute mean and std.
  1333. T mean = Norm1(data_(t)) / T(Nl);
  1334. T std(T(0));
  1335. for (int l = 0; l < Nl; l++)
  1336. {
  1337. T tmp = data_(t)(l) - mean;
  1338. std += tmp * tmp;
  1339. }
  1340. std = sqrt(std / T(Nl));
  1341. T min = mean - std * multiple_std;
  1342. min = min < T(0) ? T(0) : min;
  1343. T max = mean + std * multiple_std;
  1344. #ifdef GPEC_WITH_LOGGER
  1345. *(this->log_ptr_) << Debug(2) << "At time t = "
  1346. << t << ", filter values below "
  1347. << setprecision(2) << fixed << min
  1348. << " and above " << setprecision(2)
  1349. << fixed << max << endl;
  1350. #endif
  1351. // Now filter.
  1352. int i(0);
  1353. if (location_index_(t).GetSize() == 0)
  1354. {
  1355. location_index_(t).Reallocate(Nl);
  1356. location_index_(t).Fill();
  1357. }
  1358. for (int l = 0; l < Nl; l++)
  1359. if (data_(t)(l) < min)
  1360. {
  1361. count_filtered++;
  1362. if (keep_threshold)
  1363. {
  1364. location_index_(t)(i) = location_index_(t)(l);
  1365. data_(t)(i++) = min;
  1366. }
  1367. #ifdef GPEC_WITH_LOGGER
  1368. *(this->log_ptr_) << Debug(3) << "Filter value "
  1369. << setprecision(2) << fixed << data_(t)(l) << " at location "
  1370. << l << " and time " << t << endl;
  1371. #endif
  1372. }
  1373. else if (data_(t)(l) > max)
  1374. {
  1375. count_filtered++;
  1376. if (keep_threshold)
  1377. {
  1378. location_index_(t)(i) = location_index_(t)(l);
  1379. data_(t)(i++) = max;
  1380. }
  1381. #ifdef GPEC_WITH_LOGGER
  1382. *(this->log_ptr_) << Debug(3) << "Filter value "
  1383. << setprecision(2) << fixed << data_(t)(l) << " at location "
  1384. << l << " and time " << t << endl;
  1385. #endif
  1386. }
  1387. else
  1388. {
  1389. location_index_(t)(i) = location_index_(t)(l);
  1390. data_(t)(i++) = data_(t)(l);
  1391. }
  1392. location_index_(t).Resize(i);
  1393. data_(t).Resize(i);
  1394. if (data_(t).GetSize() == 0)
  1395. forecast_(t).Clear();
  1396. if (data_(t).GetSize() == Nl_)
  1397. location_index_(t).Clear();
  1398. }
  1399. #ifdef GPEC_WITH_LOGGER
  1400. *(this->log_ptr_) << Debug(1) << "Filtered "
  1401. << count_filtered << " values." << endl;
  1402. #endif
  1403. AddComment("filtered " + to_str(count_filtered) + " values with"
  1404. + " standard deviation times " + to_str(multiple_std));
  1405. }
  1406. // Filter values below or above given percentile.
  1407. template<class T>
  1408. void ClassContainerBase<T>::FilterPercentile(const T &percentile, int t_begin, int t_end,
  1409. const bool keep_threshold)
  1410. {
  1411. if (percentile <= T(0) || percentile >= T(1))
  1412. throw GPEC::Error("Percentile should be between ]0, 1[, got " + to_str(percentile));
  1413. check_index(0, Nt_, t_begin);
  1414. t_end = t_end == 0 ? Nt_ : t_end;
  1415. #ifdef GPEC_WITH_LOGGER
  1416. *(this->log_ptr_) << Info() << "Filter values with percentile "
  1417. << percentile << " between timesteps ["
  1418. << t_begin << ", " << t_end << "[" << endl;
  1419. #endif
  1420. int count_filtered(0);
  1421. // At each time step, compute the percentile value and remove values which are
  1422. // superior if percentile > 0.5, inferior otherwise.
  1423. for (int t = t_begin; t < t_end; t++)
  1424. if (data_(t).GetSize() > 0)
  1425. {
  1426. int Nl = data_(t).GetSize();
  1427. Vector<T> data_ascending = data_(t);
  1428. Sort(data_ascending);
  1429. Vector<T> data_percentile_rank(Nl);
  1430. for (int l = 0; l < Nl; l++)
  1431. data_percentile_rank(l) = (T(l) - T(0.5)) / T(Nl);
  1432. T percentile_value;
  1433. if (percentile < data_percentile_rank(0))
  1434. percentile_value = data_ascending(0);
  1435. else if (percentile > data_percentile_rank(Nl - 1))
  1436. percentile_value = data_ascending(Nl - 1);
  1437. else
  1438. {
  1439. int k(0);
  1440. for (k = 0; k < Nl; k++)
  1441. if (percentile < data_percentile_rank(k))
  1442. {
  1443. k--;
  1444. break;
  1445. }
  1446. percentile_value = data_ascending(k)
  1447. + (percentile - data_percentile_rank(k))
  1448. / (data_percentile_rank(k + 1) - data_percentile_rank(k))
  1449. * (data_ascending(k + 1) - data_ascending(k));
  1450. }
  1451. #ifdef GPEC_WITH_LOGGER
  1452. *(this->log_ptr_) << Debug(2) << "At time t = "
  1453. << t << ", computed percentile value = "
  1454. << percentile_value << endl;
  1455. #endif
  1456. // Now filter.
  1457. int i(0);
  1458. if (location_index_(t).GetSize() == 0)
  1459. {
  1460. location_index_(t).Reallocate(Nl);
  1461. location_index_(t).Fill();
  1462. }
  1463. for (int l = 0; l < Nl; l++)
  1464. if (percentile < T(0.5) && data_(t)(l) < percentile_value)
  1465. {
  1466. count_filtered++;
  1467. if (keep_threshold)
  1468. {
  1469. location_index_(t)(i) = location_index_(t)(l);
  1470. data_(t)(i++) = percentile_value;
  1471. }
  1472. #ifdef GPEC_WITH_LOGGER
  1473. *(this->log_ptr_) << Debug(3) << "Filter value "
  1474. << setprecision(2) << fixed << data_(t)(l) << " at location "
  1475. << l << " and time " << t << endl;
  1476. #endif
  1477. }
  1478. else if (percentile >= T(0.5) && data_(t)(l) > percentile_value)
  1479. {
  1480. count_filtered++;
  1481. if (keep_threshold)
  1482. {
  1483. location_index_(t)(i) = location_index_(t)(l);
  1484. data_(t)(i++) = percentile_value;
  1485. }
  1486. #ifdef GPEC_WITH_LOGGER
  1487. *(this->log_ptr_) << Debug(3) << "Filter value "
  1488. << setprecision(2) << fixed << data_(t)(l) << " at location "
  1489. << l << " and time " << t << endl;
  1490. #endif
  1491. }
  1492. else
  1493. {
  1494. location_index_(t)(i) = location_index_(t)(l);
  1495. data_(t)(i++) = data_(t)(l);
  1496. }
  1497. location_index_(t).Resize(i);
  1498. data_(t).Resize(i);
  1499. if (data_(t).GetSize() == 0)
  1500. forecast_(t).Clear();
  1501. if (data_(t).GetSize() == Nl_)
  1502. location_index_(t).Clear();
  1503. }
  1504. #ifdef GPEC_WITH_LOGGER
  1505. *(this->log_ptr_) << Debug(1) << "Filtered "
  1506. << count_filtered << " values." << endl;
  1507. #endif
  1508. AddComment("filtered " + to_str(count_filtered) + " values with"
  1509. + " percentile " + to_str(percentile));
  1510. }
  1511. // Filter value below a threshold.
  1512. template<class T>
  1513. void ClassContainerBase<T>::FilterThresholdExceedance(const T &threshold,
  1514. const bool reduce_location)
  1515. {
  1516. if (threshold < value_min_)
  1517. return;
  1518. if (threshold >= value_max_)
  1519. throw GPEC::Error("Threshold value is greater than the container maximum admissible value.");
  1520. for (int t = 0; t < Nt_; t++)
  1521. {
  1522. int Nl = data_(t).GetSize();
  1523. int i(0);
  1524. if (Nl > 0)
  1525. {
  1526. if (location_index_(t).GetSize() == 0)
  1527. {
  1528. location_index_(t).Reallocate(Nl);
  1529. location_index_(t).Fill();
  1530. }
  1531. if (reduce_location)
  1532. {
  1533. for (int l = 0; l < Nl; l++)
  1534. if (data_(t)(l) >= threshold)
  1535. {
  1536. location_index_(t)(i) = location_index_(t)(l);
  1537. data_(t)(i++) = data_(t)(l);
  1538. }
  1539. location_index_(t).Resize(i);
  1540. data_(t).Resize(i);
  1541. }
  1542. else
  1543. for (int l = 0; l < Nl; l++)
  1544. if (data_(t)(l) < threshold)
  1545. data_(t)(l) = T(0);
  1546. if (data_(t).GetSize() == 0)
  1547. forecast_(t).Clear();
  1548. if (data_(t).GetSize() == Nl_)
  1549. location_index_(t).Clear();
  1550. }
  1551. }
  1552. }
  1553. // MPI Communication.
  1554. #ifdef GPEC_WITH_MPI
  1555. template<class T>
  1556. void ClassContainerBase<T>::MPI_SendRecv(const int &send_rank, const int &recv_rank)
  1557. {
  1558. int isize, itag(0);
  1559. if (this->rank_ == recv_rank)
  1560. {
  1561. MPI::COMM_WORLD.Recv(&isize, 1, MPI::INT, send_rank, itag++);
  1562. char *str = new char[isize];
  1563. MPI::COMM_WORLD.Recv(str, isize, MPI::CHAR, send_rank, itag++);
  1564. type_ = str;
  1565. MPI::COMM_WORLD.Recv(&isize, 1, MPI::INT, send_rank, itag++);
  1566. str = new char[isize];
  1567. MPI::COMM_WORLD.Recv(str, isize, MPI::CHAR, send_rank, itag++);
  1568. name_ = str;
  1569. MPI::COMM_WORLD.Recv(&isize, 1, MPI::INT, send_rank, itag++);
  1570. str = new char[isize];
  1571. MPI::COMM_WORLD.Recv(str, isize, MPI::CHAR, send_rank, itag++);
  1572. species_ = str;
  1573. MPI::COMM_WORLD.Recv(&isize, 1, MPI::INT, send_rank, itag++);
  1574. str = new char[isize];
  1575. MPI::COMM_WORLD.Recv(str, isize, MPI::CHAR, send_rank, itag++);
  1576. comment_ = str;
  1577. delete[] str;
  1578. MPI::COMM_WORLD.Recv(&isize, 1, MPI::INT, send_rank, itag++);
  1579. date_begin_ = get_date_from_int(isize);
  1580. MPI::COMM_WORLD.Recv(&isize, 1, MPI::INT, send_rank, itag++);
  1581. date_end_ = get_date_from_int(isize);
  1582. MPI::COMM_WORLD.Recv(&Nt_day_, 1, MPI::INT, send_rank, itag++);
  1583. MPI::COMM_WORLD.Recv(&Nt_, 1, MPI::INT, send_rank, itag++);
  1584. MPI::COMM_WORLD.Recv(&Nd_, 1, MPI::INT, send_rank, itag++);
  1585. MPI::COMM_WORLD.Recv(&delta_t_, 1, GPEC_MPI_REAL, send_rank, itag++);
  1586. MPI::COMM_WORLD.Recv(&Nl_, 1, MPI::INT, send_rank, itag++);
  1587. MPI::COMM_WORLD.Recv(&value_min_, 1, GPEC_MPI_REAL, send_rank, itag++);
  1588. MPI::COMM_WORLD.Recv(&value_max_, 1, GPEC_MPI_REAL, send_rank, itag++);
  1589. location_index_.Reallocate(Nt_);
  1590. data_.Reallocate(Nt_);
  1591. forecast_.Reallocate(Nt_);
  1592. for (int t = 0; t < Nt_; t++)
  1593. {
  1594. MPI::COMM_WORLD.Recv(&isize, 1, MPI::INT, send_rank, itag++);
  1595. if (isize > 0)
  1596. {
  1597. if (isize < Nl_)
  1598. {
  1599. location_index_(t).Reallocate(isize);
  1600. MPI::COMM_WORLD.Recv(location_index_(t).GetData(), isize, MPI::INT, send_rank, itag++);
  1601. }
  1602. data_(t).Reallocate(isize);
  1603. forecast_(t).Reallocate(1);
  1604. MPI::COMM_WORLD.Recv(data_(t).GetData(), isize, GPEC_MPI_REAL, send_rank, itag++);
  1605. MPI::COMM_WORLD.Recv(forecast_(t).GetData(), 1, MPI::INT, send_rank, itag++);
  1606. }
  1607. }
  1608. }
  1609. else if (this->rank_ == send_rank)
  1610. {
  1611. isize = int(type_.size());
  1612. MPI::COMM_WORLD.Send(&isize, 1, MPI::INT, recv_rank, itag++);
  1613. MPI::COMM_WORLD.Send(type_.data(), isize, MPI::CHAR, recv_rank, itag++);
  1614. isize = int(name_.size());
  1615. MPI::COMM_WORLD.Send(&isize, 1, MPI::INT, recv_rank, itag++);
  1616. MPI::COMM_WORLD.Send(name_.data(), isize, MPI::CHAR, recv_rank, itag++);
  1617. isize = int(species_.size());
  1618. MPI::COMM_WORLD.Send(&isize, 1, MPI::INT, recv_rank, itag++);
  1619. MPI::COMM_WORLD.Send(species_.data(), isize, MPI::CHAR, recv_rank, itag++);
  1620. isize = int(comment_.size());
  1621. MPI::COMM_WORLD.Send(&isize, 1, MPI::INT, recv_rank, itag++);
  1622. MPI::COMM_WORLD.Send(comment_.data(), isize, MPI::CHAR, recv_rank, itag++);
  1623. isize = get_int_from_date(date_begin_);
  1624. MPI::COMM_WORLD.Send(&isize, 1, MPI::INT, recv_rank, itag++);
  1625. isize = get_int_from_date(date_end_);
  1626. MPI::COMM_WORLD.Send(&isize, 1, MPI::INT, recv_rank, itag++);
  1627. MPI::COMM_WORLD.Send(&Nt_day_, 1, MPI::INT, recv_rank, itag++);
  1628. MPI::COMM_WORLD.Send(&Nt_, 1, MPI::INT, recv_rank, itag++);
  1629. MPI::COMM_WORLD.Send(&Nd_, 1, MPI::INT, recv_rank, itag++);
  1630. MPI::COMM_WORLD.Send(&delta_t_, 1, GPEC_MPI_REAL, recv_rank, itag++);
  1631. MPI::COMM_WORLD.Send(&Nl_, 1, MPI::INT, recv_rank, itag++);
  1632. MPI::COMM_WORLD.Send(&value_min_, 1, GPEC_MPI_REAL, recv_rank, itag++);
  1633. MPI::COMM_WORLD.Send(&value_max_, 1, GPEC_MPI_REAL, recv_rank, itag++);
  1634. for (int t = 0; t < Nt_; t++)
  1635. {
  1636. isize = data_(t).GetSize();
  1637. MPI::COMM_WORLD.Send(&isize, 1, MPI::INT, recv_rank, itag++);
  1638. if (isize > 0)
  1639. {
  1640. if (isize < Nl_)
  1641. MPI::COMM_WORLD.Send(location_index_(t).GetData(), isize, MPI::INT, recv_rank, itag++);
  1642. MPI::COMM_WORLD.Send(data_(t).GetData(), isize, GPEC_MPI_REAL, recv_rank, itag++);
  1643. MPI::COMM_WORLD.Send(forecast_(t).GetData(), 1, MPI::INT, recv_rank, itag++);
  1644. }
  1645. }
  1646. }
  1647. }
  1648. template<class T>
  1649. void ClassContainerBase<T>::MPI_Gather(const int &recv_rank)
  1650. {
  1651. for (int t = 0; t < Nt_; t++)
  1652. {
  1653. Vector1I rcounts(this->Nrank_);
  1654. rcounts.Zero();
  1655. rcounts(this->rank_) = data_(t).GetSize();
  1656. MPI::COMM_WORLD.Gather(rcounts.GetData() + this->rank_, 1, MPI::INT,
  1657. rcounts.GetData(), 1, MPI::INT, recv_rank);
  1658. int rcount(0);
  1659. Vector1I displs(this->Nrank_);
  1660. displs.Zero();
  1661. if (this->rank_ == recv_rank)
  1662. {
  1663. rcount = rcounts(0);
  1664. for (int irank = 1; irank < this->Nrank_; irank++)
  1665. {
  1666. displs(irank) = rcount;
  1667. rcount += rcounts(irank);
  1668. }
  1669. }
  1670. MPI::COMM_WORLD.Bcast(&rcount, 1, MPI::INT, recv_rank);
  1671. if (rcount == 0)
  1672. continue;
  1673. Vector1I recv_buf_int;
  1674. Vector1T recv_buf_real;
  1675. if (this->rank_ == recv_rank)
  1676. {
  1677. recv_buf_int.Reallocate(rcount);
  1678. recv_buf_real.Reallocate(rcount);
  1679. }
  1680. int scount = data_(t).GetSize();
  1681. MPI::COMM_WORLD.Gatherv(location_index_(t).GetData(), scount, MPI::INT,
  1682. recv_buf_int.GetData(), rcounts.GetData(),
  1683. displs.GetData(), MPI::INT, recv_rank);
  1684. MPI::COMM_WORLD.Gatherv(data_(t).GetData(), scount, GPEC_MPI_REAL,
  1685. recv_buf_real.GetData(), rcounts.GetData(),
  1686. displs.GetData(), GPEC_MPI_REAL, recv_rank);
  1687. if (this->rank_ == recv_rank)
  1688. {
  1689. location_index_(t) = recv_buf_int;
  1690. data_(t) = recv_buf_real;
  1691. for (int l = 1; l < location_index_(t).GetSize(); l++)
  1692. if (location_index_(t)(l - 1) > location_index_(t)(l))
  1693. {
  1694. Sort(location_index_(t), data_(t));
  1695. break;
  1696. }
  1697. if (rcount == Nl_)
  1698. location_index_(t).Clear();
  1699. }
  1700. }
  1701. }
  1702. template<class T>
  1703. void ClassContainerBase<T>::MPI_Scatter(const int &send_rank)
  1704. {
  1705. this->set_location_per_rank(this->Nl_);
  1706. int idate_begin, idate_end;
  1707. if (this->rank_ == send_rank)
  1708. {
  1709. idate_begin = get_int_from_date(date_begin_);
  1710. idate_end = get_int_from_date(date_end_);
  1711. }
  1712. MPI::COMM_WORLD.Bcast(&idate_begin, 1, MPI::INT, send_rank);
  1713. MPI::COMM_WORLD.Bcast(&idate_end, 1, MPI::INT, send_rank);
  1714. if (this->rank_ != send_rank)
  1715. {
  1716. date_begin_ = get_date_from_int(idate_begin);
  1717. date_end_ = get_date_from_int(idate_end);
  1718. set_Nt();
  1719. set_Nd();
  1720. location_index_.Reallocate(Nt_);
  1721. data_.Reallocate(Nt_);
  1722. forecast_.Reallocate(Nt_);
  1723. }
  1724. for (int t = 0; t < Nt_; t++)
  1725. {
  1726. int Nl = data_(t).GetSize();
  1727. MPI::COMM_WORLD.Bcast(&Nl, 1, MPI::INT, send_rank);
  1728. if (Nl == 0)
  1729. continue;
  1730. int rcount;
  1731. Vector1I scounts(this->Nrank_), displs(this->Nrank_);
  1732. if (Nl < this->Nl_)
  1733. {
  1734. if (this->rank_ == send_rank)
  1735. {
  1736. int irank(0), count(0);
  1737. int loc = this->Nlocation_rank_(0);
  1738. for (int l = 0; l < location_index_(t).GetSize(); l++)
  1739. {
  1740. count++;
  1741. if (location_index_(t)(l) >= loc)
  1742. {
  1743. scounts(irank) = count;
  1744. displs(irank) = l;
  1745. count = 0;
  1746. irank++;
  1747. loc = this->location_offset_rank_(irank) + this->Nlocation_rank_(irank);
  1748. }
  1749. }
  1750. }
  1751. }
  1752. else
  1753. {
  1754. scounts = this->Nlocation_rank_;
  1755. displs = this->location_offset_rank_;
  1756. }
  1757. MPI::COMM_WORLD.Bcast(scounts.GetData(), this->Nrank_, MPI::INT, send_rank);
  1758. rcount = scounts(this->rank_);
  1759. if (this->rank_ != send_rank)
  1760. {
  1761. data_(t).Reallocate(rcount);
  1762. forecast_(t).Reallocate(1);
  1763. }
  1764. if (Nl < this->Nl_)
  1765. {
  1766. Vector1I send_buf;
  1767. if (this->rank_ == send_rank)
  1768. send_buf = location_index_(t);
  1769. location_index_(t).Reallocate(rcount);
  1770. MPI::COMM_WORLD.Scatterv(send_buf.GetData(), scounts.GetData(),
  1771. displs.GetData(), MPI::INT, location_index_(t).GetData(),
  1772. rcount, MPI::INT, send_rank);
  1773. }
  1774. else
  1775. location_index_(t) = this->location_rank_;
  1776. Vector1T send_buf;
  1777. if (this->rank_ == send_rank)
  1778. send_buf = data_(t);
  1779. data_(t).Reallocate(rcount);
  1780. MPI::COMM_WORLD.Scatterv(send_buf.GetData(), scounts.GetData(), displs.GetData(),
  1781. GPEC_MPI_REAL, data_(t).GetData(),
  1782. rcount, GPEC_MPI_REAL, send_rank);
  1783. forecast_(t).Resize(1);
  1784. MPI::COMM_WORLD.Bcast(forecast_(t).GetData(), 1, MPI::INT, send_rank);
  1785. }
  1786. }
  1787. #endif
  1788. }
  1789. #define GPEC_FILE_CLASS_CONTAINER_BASE_CXX
  1790. #endif