00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef __CALCIUM_COUPLING_POLICY__
00029 #define __CALCIUM_COUPLING_POLICY__
00030
00031 #include <vector>
00032 #include <map>
00033
00034 #include "DisplayPair.hxx"
00035 #include "CouplingPolicy.hxx"
00036 #include "AdjacentFunctor.hxx"
00037 #include <boost/lambda/lambda.hpp>
00038 #include <boost/utility/enable_if.hpp>
00039 #include <boost/type_traits/is_arithmetic.hpp>
00040 #include "CalciumTypes.hxx"
00041 #include "CalciumException.hxx"
00042
00043
00044
00045 class CalciumCouplingPolicy : public CouplingPolicy {
00046
00047
00048 public:
00049
00050 template <typename T_TIME, typename T_TAG > class InternalDataIdContainer;
00051 template <typename T_TIME, typename T_TAG > friend class InternalDataIdContainer;
00052 template <typename DataManipulator,
00053 class EnableIf > friend class BoundedDataIdProcessor;
00054 template <typename DataManipulator > friend class EraseDataIdProcessor;
00055 template <typename DataManipulator > friend class EraseDataIdBeforeOrAfterTagProcessor;
00056 template <typename DataManipulator > friend class DisconnectProcessor;
00057
00058 typedef CalciumTypes::DependencyType DependencyType;
00059 typedef CalciumTypes::DateCalSchem DateCalSchem;
00060 typedef CalciumTypes::InterpolationSchem InterpolationSchem;
00061 typedef CalciumTypes::ExtrapolationSchem ExtrapolationSchem;
00062 typedef CalciumTypes::DisconnectDirective DisconnectDirective;
00063
00064 private:
00065
00066 DependencyType _dependencyType;
00067 size_t _storageLevel;
00068 DateCalSchem _dateCalSchem;
00069 InterpolationSchem _interpolationSchem;
00070 ExtrapolationSchem _extrapolationSchem;
00071 double _alpha;
00072 double _deltaT;
00073 DisconnectDirective _disconnectDirective;
00074
00075 public:
00076 CalciumCouplingPolicy();
00077
00078 void setDependencyType (DependencyType dependencyType);
00079 DependencyType getDependencyType () const;
00080
00081 void setStorageLevel (size_t storageLevel);
00082 size_t getStorageLevel () const;
00083
00084 void setDateCalSchem (DateCalSchem dateCalSchem);
00085 DateCalSchem getDateCalSchem () const;
00086
00087 void setAlpha(double alpha);
00088 double getAlpha() const ;
00089
00090 void setDeltaT(double deltaT );
00091 double getDeltaT() const ;
00092
00093 void setInterpolationSchem (InterpolationSchem interpolationSchem);
00094 void setExtrapolationSchem (ExtrapolationSchem extrapolationSchem);
00095 InterpolationSchem getInterpolationSchem () const ;
00096 ExtrapolationSchem getExtrapolationSchem () const ;
00097
00098
00099
00100
00101 typedef double TimeType;
00102 typedef long TagType;
00103 typedef std::pair< TimeType , TagType > DataId;
00104 typedef InternalDataIdContainer < TimeType , TagType > DataIdContainer;
00105 typedef std::vector< DataId >::iterator iterator;
00106
00107 template <typename T_TIME, typename T_TAG >
00108 struct InternalDataIdContainer;
00109
00110 inline TimeType getTime(const DataId &dataId) const { return dataId.first;}
00111 inline TagType getTag (const DataId &dataId) const { return dataId.second;}
00112
00113 template <typename DataManipulator,
00114 class EnableIf = void > struct BoundedDataIdProcessor;
00115
00116 template <typename DataManipulator> struct EraseDataIdProcessor;
00117 template <typename DataManipulator> struct EraseDataIdBeforeOrAfterTagProcessor;
00118 template <typename DataManipulator> struct DisconnectProcessor;
00119
00120
00121
00122
00123
00124
00125
00126 template < typename AssocContainer >
00127 bool isDataIdConveniant( AssocContainer & storedDatas,
00128 const typename AssocContainer::key_type & expectedDataId,
00129 bool & isEqual, bool & isBounded,
00130 typename AssocContainer::iterator & wDataIt1) const;
00131
00132 TimeType getEffectiveTime(TimeType ti, TimeType tf);
00133
00134 void disconnect(bool provideLastGivenValue);
00135
00136 };
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 template <typename T_TIME, typename T_TAG >
00147 struct CalciumCouplingPolicy::InternalDataIdContainer : public std::vector< std::pair< T_TIME,T_TAG> > {
00148 typedef std::vector < DataId > DataIdVect;
00149
00150 InternalDataIdContainer(const DataId & dataId,
00151 const CalciumCouplingPolicy & policy
00152 ):std::vector< std::pair< T_TIME,T_TAG> >() {
00153
00154 switch (policy._dependencyType) {
00155 case CalciumTypes::TIME_DEPENDENCY:
00156 this->push_back(DataId(dataId.first,0));
00157 break;
00158 case CalciumTypes::ITERATION_DEPENDENCY:
00159 this->push_back(DataId(0,dataId.second));
00160 break;
00161 default:
00162 throw(CalciumException(CalciumTypes::CPIT,LOC("The dependency type must be set by setDependencyType before calling DataIdContainer contructor")));
00163 break;
00164 }
00165 };
00166 };
00167
00168
00169 template <typename DataManipulator, class EnableIf >
00170 struct CalciumCouplingPolicy::BoundedDataIdProcessor{
00171 BoundedDataIdProcessor(const CouplingPolicy & couplingPolicy) {};
00172 template < typename Iterator, typename DataId >
00173 void inline apply(typename iterator_t<Iterator>::value_type & data,
00174 const DataId & dataId,
00175 const Iterator & it1) const {
00176 typedef typename iterator_t<Iterator>::value_type value_type;
00177 #ifdef MYDEBUG
00178 std::cout << "-------- Calcium Generic BoundedDataIdProcessor.apply() called " << std::endl;
00179 #endif
00180
00181 }
00182 };
00183
00184
00185 template <typename DataManipulator >
00186 struct CalciumCouplingPolicy::BoundedDataIdProcessor<
00187 DataManipulator,
00188 typename boost::enable_if< boost::is_float< typename DataManipulator::InnerType> >::type > {
00189
00190 const CalciumCouplingPolicy & _couplingPolicy;
00191
00192 BoundedDataIdProcessor(const CalciumCouplingPolicy &couplingPolicy):
00193 _couplingPolicy(couplingPolicy) {};
00194
00195
00196 template < typename MapIterator >
00197 void inline apply (typename iterator_t<MapIterator>::value_type & data,
00198 const DataId & dataId, const MapIterator & it1) const {
00199
00200 typedef typename iterator_t<MapIterator>::value_type value_type;
00201 typedef typename DataManipulator::InnerType InnerType;
00202 typedef typename DataManipulator::Type Type;
00203
00204 MapIterator it2=it1; ++it2;
00205 size_t dataSize1 = DataManipulator::size(it1->second);
00206 #ifdef MYDEBUG
00207 std::cout << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : Taille de donnée dataId1 : " << dataSize1 << std::endl;
00208 #endif
00209
00210
00211
00212 size_t dataSize2 = DataManipulator::size(it2->second);
00213 #ifdef MYDEBUG
00214 std::cout << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : Taille de donnée dataId2 : " << dataSize2 << std::endl;
00215 #endif
00216
00217 size_t dataSize = std::min< size_t >( dataSize1, dataSize2 );
00218 DataId dataId2 = it2->first;
00219 DataId dataId1 = it1->first;
00220 TimeType t2 = dataId2.first;
00221 TimeType t1 = dataId1.first;
00222 #ifdef MYDEBUG
00223 std::cout << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : Valeur de t1 : " << t1 << std::endl;
00224 std::cout << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : Valeur de t2 : " << t2 << std::endl;
00225 #endif
00226 TimeType t = dataId.first;
00227 #ifdef MYDEBUG
00228 std::cout << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : Valeur de t : " << t << std::endl;
00229 #endif
00230 TimeType timeDiff = t2-t1;
00231 #ifdef MYDEBUG
00232 std::cout << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : Valeur de timeDiff : " << timeDiff << std::endl;
00233 #endif
00234 TimeType coeff = (t2-t)/timeDiff;
00235 #ifdef MYDEBUG
00236 std::cout << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : Valeur de coeff : " << coeff << std::endl;
00237 #endif
00238
00239 InnerType const * const InIt1 = DataManipulator::getPointer(it1->second);
00240 #ifdef MYDEBUG
00241 std::cout << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : Données à t1 : " << std::endl;
00242 std::copy(InIt1,InIt1+dataSize1,std::ostream_iterator<InnerType>(std::cout," "));
00243 std::cout << std::endl;
00244 #endif
00245 InnerType const * const InIt2 = DataManipulator::getPointer(it2->second);
00246 #ifdef MYDEBUG
00247 std::cout << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : Données à t2 : " << std::endl;
00248 std::copy(InIt2,InIt2+dataSize2,std::ostream_iterator<InnerType>(std::cout," "));
00249 std::cout << std::endl;
00250 #endif
00251 Type dataOut = DataManipulator::create(dataSize);
00252 InnerType * const OutIt = DataManipulator::getPointer(dataOut);
00253
00254 #ifdef MYDEBUG
00255 std::cerr << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : interpolationSchem : " << _couplingPolicy._interpolationSchem << std::endl;
00256 std::cerr << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : alpha : " << _couplingPolicy._alpha << std::endl;
00257 std::cerr << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : datecalschem : " << _couplingPolicy._dateCalSchem << std::endl;
00258 std::cerr << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : storageLevel : " << _couplingPolicy._storageLevel << std::endl;
00259 #endif
00260 if ( timeDiff == 0.0 || _couplingPolicy._interpolationSchem == CalciumTypes::L0_SCHEM ) {
00261 std::copy(InIt1,InIt1+dataSize,OutIt);
00262 } else {
00263
00264 boost::lambda::placeholder1_type _1;
00265 boost::lambda::placeholder2_type _2;
00266
00267
00268 std::transform(InIt1,InIt1+dataSize,InIt2,OutIt,
00269 ( _1 - _2 ) * coeff + _2 );
00270
00271
00272
00273
00274 }
00275 #ifdef MYDEBUG
00276 std::cout << "-------- CalciumCouplingPolicy::BoundedDataIdProcessor : Données calculées à t : " << std::endl;
00277 std::copy(OutIt,OutIt+dataSize,std::ostream_iterator<InnerType>(std::cout," "));
00278 std::cout << std::endl;
00279 #endif
00280 data = dataOut;
00281
00282 }
00283 };
00284
00285
00286
00287
00288
00289
00290
00291 template < typename AssocContainer >
00292 bool CalciumCouplingPolicy::isDataIdConveniant( AssocContainer & storedDatas, const typename AssocContainer::key_type & expectedDataId,
00293 bool & isEqual, bool & isBounded, typename AssocContainer::iterator & wDataIt1) const {
00294
00295
00296 typedef typename AssocContainer::key_type key_type;
00297 AdjacentFunctor< key_type > af(expectedDataId);
00298 if ( _dependencyType == CalciumTypes::TIME_DEPENDENCY )
00299 {
00300 #ifdef MYDEBUG
00301 std::cout << "-------- time expected : " << expectedDataId.first << std::endl;
00302 std::cout << "-------- time expected corrected : " << expectedDataId.first*(1.0-_deltaT) << std::endl;
00303 #endif
00304 af.setMaxValue(key_type(expectedDataId.first*(1.0-_deltaT),0));
00305 }
00306 isBounded = false;
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 typename AssocContainer::iterator prev = storedDatas.begin();
00324 typename AssocContainer::iterator current = prev;
00325 while ( (current != storedDatas.end()) && !af(current->first) )
00326 {
00327 #ifdef MYDEBUG
00328 std::cerr << "------- stored time : " << current->first << std::endl;
00329 #endif
00330
00331 prev = current++;
00332 }
00333
00334 isEqual = af.isEqual();
00335
00336
00337
00338 if ( _dependencyType == CalciumTypes::TIME_DEPENDENCY) isBounded = af.isBounded();
00339
00340 if ( isEqual ) wDataIt1 = current;
00341 else
00342 if (isBounded) wDataIt1 = prev;
00343 else
00344 wDataIt1 = storedDatas.end();
00345
00346 #ifdef MYDEBUG
00347 std::cout << "-------- isDataIdConvenient : isEqual : " << isEqual << " , isBounded " << isBounded << std::endl;
00348 #endif
00349
00350 return isEqual || isBounded;
00351 }
00352
00353
00354 template < typename DataManipulator >
00355 struct CalciumCouplingPolicy::EraseDataIdBeforeOrAfterTagProcessor
00356 {
00357 CalciumCouplingPolicy &_couplingPolicy;
00358
00359 EraseDataIdBeforeOrAfterTagProcessor(CalciumCouplingPolicy &couplingPolicy):
00360 _couplingPolicy(couplingPolicy) {};
00361
00362 template < typename Container,typename TimeType,typename TagType >
00363 void apply(Container & storedDatas, TimeType time, TagType tag, bool before) const
00364 {
00365 typedef typename Container::iterator iterator;
00366 typedef typename Container::reverse_iterator riterator;
00367
00368 if(_couplingPolicy._dependencyType == CalciumTypes::TIME_DEPENDENCY)
00369 {
00370 if(before)
00371 {
00372 iterator it=storedDatas.begin();
00373 while(it != storedDatas.end() && it->first.first <= time)
00374 {
00375 DataManipulator::delete_data(it->second);
00376 storedDatas.erase(it);
00377 it=storedDatas.begin();
00378 }
00379 }
00380 else
00381 {
00382 riterator it=storedDatas.rbegin();
00383 while(it != storedDatas.rend() && it->first.first >= time)
00384 {
00385 DataManipulator::delete_data(it->second);
00386 storedDatas.erase(it->first);
00387 it=storedDatas.rbegin();
00388 }
00389 }
00390 }
00391 else
00392 {
00393 if(before)
00394 {
00395 iterator it=storedDatas.begin();
00396 while(it != storedDatas.end() && it->first.second <= tag)
00397 {
00398 DataManipulator::delete_data(it->second);
00399 storedDatas.erase(it);
00400 it=storedDatas.begin();
00401 }
00402 }
00403 else
00404 {
00405 riterator it=storedDatas.rbegin();
00406 while(it != storedDatas.rend() && it->first.second >= tag)
00407 {
00408 DataManipulator::delete_data(it->second);
00409 storedDatas.erase(it->first);
00410 it=storedDatas.rbegin();
00411 }
00412 }
00413 }
00414 }
00415 };
00416
00417
00418
00419
00420
00421
00422
00423
00424 template < typename DataManipulator >
00425 struct CalciumCouplingPolicy::EraseDataIdProcessor {
00426
00427 CalciumCouplingPolicy &_couplingPolicy;
00428
00429 EraseDataIdProcessor(CalciumCouplingPolicy &couplingPolicy):
00430 _couplingPolicy(couplingPolicy) {};
00431
00432 template < typename Container >
00433 void apply(Container & storedDatas,
00434 typename Container::iterator & wDataIt1 ) const {
00435
00436 typedef typename Container::key_type key_type;
00437 typedef typename Container::value_type value_type;
00438 typedef typename Container::iterator iterator;
00439
00440 #ifdef MYDEBUG
00441 std::cout << "-------- CalciumCouplingPolicy::eraseDataId, storedDatasSize : " << storedDatas.size() << std::endl;
00442 #endif
00443
00444 if ( _couplingPolicy._storageLevel == CalciumTypes::UNLIMITED_STORAGE_LEVEL ) return;
00445
00446 size_t storedDatasSize = storedDatas.size();
00447 long s = storedDatasSize - _couplingPolicy._storageLevel;
00448 if (s > 0 ) {
00449 size_t dist=distance(storedDatas.begin(),wDataIt1);
00450 for (int i=0; i<s; ++i) {
00451
00452 DataManipulator::delete_data((*storedDatas.begin()).second);
00453 storedDatas.erase(storedDatas.begin());
00454 }
00455
00456 if (dist < s ) {
00457 throw(CalciumException(CalciumTypes::CPNTNULL,LOC(OSS()<< "StorageLevel management "
00458 << _couplingPolicy._storageLevel <<
00459 " has just removed the data to send")));
00460 }
00461 }
00462 #ifdef MYDEBUG
00463 std::cout << "-------- CalciumCouplingPolicy::eraseDataId, new storedDatasSize : " << storedDatas.size() << std::endl;
00464 #endif
00465 return;
00466
00467 }
00468 };
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 template < typename DataManipulator >
00479 struct CalciumCouplingPolicy::DisconnectProcessor {
00480
00481 const CalciumCouplingPolicy & _couplingPolicy;
00482
00483 DisconnectProcessor(const CalciumCouplingPolicy & couplingPolicy):
00484 _couplingPolicy(couplingPolicy) {};
00485
00486 template < typename Container, typename DataId >
00487 bool apply(Container & storedDatas,
00488 const DataId & expectedDataId,
00489 typename Container::iterator & wDataIt1 ) const {
00490
00491 typedef typename Container::key_type key_type;
00492 typedef typename Container::value_type value_type;
00493 typedef typename Container::iterator iterator;
00494
00495
00496 #ifdef MYDEBUG
00497 std::cout << "-------- CalciumCouplingPolicy::DisconnectProcessor MARK1 ("<< _couplingPolicy._disconnectDirective<<") --------" << std::endl;
00498 #endif
00499 if ( (_couplingPolicy._disconnectDirective) == (CalciumTypes::UNDEFINED_DIRECTIVE) ) return false;
00500
00501 #ifdef MYDEBUG
00502 std::cout << "-------- CalciumCouplingPolicy::DisconnectProcessor MARK2 --------" << std::endl;
00503 #endif
00504
00505
00506 if ( _couplingPolicy._disconnectDirective == CalciumTypes::CP_ARRET )
00507 throw(CalciumException(CalciumTypes::CPINARRET,LOC(OSS()<< "CP_ARRET directive"
00508 << " interrupts all further data reading")));
00509 #ifdef MYDEBUG
00510 std::cout << "-------- CalciumCouplingPolicy::DisconnectProcessor MARK3 --------" << std::endl;
00511 #endif
00512
00513
00514
00515
00516 if ( storedDatas.empty() )
00517 throw(CalciumException(CalciumTypes::CPNTNULL,LOC(OSS()<< "CP_CONT directive"
00518 << " is active but no data is available.")));
00519
00520
00521
00522
00523
00524 #ifdef MYDEBUG
00525 std::cout << "-------- CalciumCouplingPolicy::DisconnectProcessor MARK4 " << expectedDataId <<" --------" << std::endl;
00526 #endif
00527
00528
00529 iterator it1 = storedDatas.lower_bound(expectedDataId);
00530 #ifdef MYDEBUG
00531 std::cout << "-------- CalciumCouplingPolicy::DisconnectProcessor MARK5 " << std::endl;
00532 for (iterator it=storedDatas.begin();it!=storedDatas.end();++it)
00533 std::cout <<" "<<(*it).first ;
00534 std::cout <<std::endl;
00535 #endif
00536
00537
00538 if (it1 == storedDatas.end())
00539 throw(CalciumException(CalciumTypes::CPNTNULL,LOC(OSS()<< "CP_CONT directive"
00540 << " is active but the requested dataId is less or equal to the last one received.")));
00541
00542 #ifdef MYDEBUG
00543 std::cout << "-------- CalciumCouplingPolicy::DisconnectProcessor MARK6 " << std::endl;
00544 #endif
00545
00546 wDataIt1 = storedDatas.end();
00547 --wDataIt1;
00548 #ifdef MYDEBUG
00549 std::cout << "-------- CalciumCouplingPolicy::DisconnectProcessor, CP_CONT : " << (*wDataIt1).first << std::endl;
00550 #endif
00551
00552 return true;
00553 }
00554 };
00555
00556 #endif