1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "MEDCouplingDefinitionTime.hxx"
22 #include "MEDCouplingFieldDouble.hxx"
26 using namespace ParaMEDMEM;
28 const double MEDCouplingDefinitionTime::EPS_DFT=1e-15;
30 MEDCouplingDefinitionTimeSlice *MEDCouplingDefinitionTimeSlice::New(const MEDCouplingFieldDouble *f, int meshId, const std::vector<int>& arrId, int fieldId) throw(INTERP_KERNEL::Exception)
32 static const char msg[]="TimeSlice::New : mismatch of arrays number of a fieldDouble and its policy !!! Internal error !!!";
34 throw INTERP_KERNEL::Exception("MEDCouplingDefinitionTimeSlice::New : empty field !");
35 switch(f->getTimeDiscretization())
40 throw INTERP_KERNEL::Exception(msg);
41 return new MEDCouplingDefinitionTimeSliceInst(f,meshId,arrId[0],fieldId);
43 case CONST_ON_TIME_INTERVAL:
46 throw INTERP_KERNEL::Exception(msg);
47 return new MEDCouplingDefinitionTimeSliceCstOnTI(f,meshId,arrId[0],fieldId);
52 throw INTERP_KERNEL::Exception(msg);
53 return new MEDCouplingDefinitionTimeSliceLT(f,meshId,arrId[0],arrId[1],fieldId);
56 throw INTERP_KERNEL::Exception("Invalide time discretization ! NO_TIME ! Impossible to build a definition time slice !");
58 throw INTERP_KERNEL::Exception("Invalide time discretization : Not recognized !");
62 MEDCouplingDefinitionTimeSlice *MEDCouplingDefinitionTimeSlice::New(TypeOfTimeDiscretization type, const std::vector<int>& tiI, const std::vector<double>& tiD) throw(INTERP_KERNEL::Exception)
67 return MEDCouplingDefinitionTimeSliceInst::New(tiI,tiD);
68 case CONST_ON_TIME_INTERVAL:
69 return MEDCouplingDefinitionTimeSliceCstOnTI::New(tiI,tiD);
71 return MEDCouplingDefinitionTimeSliceLT::New(tiI,tiD);
73 throw INTERP_KERNEL::Exception("MEDCouplingDefinitionTimeSlice::New : unrecognized time discretization type !");
77 bool MEDCouplingDefinitionTimeSlice::isEqual(const MEDCouplingDefinitionTimeSlice& other, double eps) const
79 if(_mesh_id!=other._mesh_id)
81 if(_array_id!=other._array_id)
83 if(_field_id!=other._field_id)
88 int MEDCouplingDefinitionTimeSlice::getStartId() const
93 int MEDCouplingDefinitionTimeSlice::getEndId() const
98 void MEDCouplingDefinitionTimeSlice::appendRepr(std::ostream& stream) const
100 stream << " *** MeshId : " << _mesh_id << " ArrayId : " << _array_id;
103 MEDCouplingDefinitionTimeSlice::MEDCouplingDefinitionTimeSlice(const MEDCouplingFieldDouble *f, int meshId, int arrId, int fieldId) throw(INTERP_KERNEL::Exception):_mesh_id(meshId),_array_id(arrId),_field_id(fieldId)
106 double t1=f->getStartTime(tmp1,tmp2);
107 double t2=f->getEndTime(tmp1,tmp2);
109 throw INTERP_KERNEL::Exception("MEDCouplingDefinitionTimeSlice : End time strictly before Start time ...");
112 bool MEDCouplingDefinitionTimeSlice::isFullyIncludedInMe(const MEDCouplingDefinitionTimeSlice *other, double eps) const
114 double t1=getStartTime();
115 double t2=getEndTime();
116 double o1=other->getStartTime();
117 double o2=other->getEndTime();
118 return o1>t1-eps && o2<t2+eps;
121 bool MEDCouplingDefinitionTimeSlice::isOverllapingWithMe(const MEDCouplingDefinitionTimeSlice *other, double eps) const
123 double t1=getStartTime();
124 double t2=getEndTime();
125 double o1=other->getStartTime();
126 double o2=other->getEndTime();
127 return (o1<t1+eps && o2<t1+eps) || (o1>t2-eps && o2>t2-eps);
130 bool MEDCouplingDefinitionTimeSlice::isAfterMe(const MEDCouplingDefinitionTimeSlice *other, double eps) const
132 double t2=getEndTime();
133 double o1=other->getStartTime();
134 double o2=other->getEndTime();
135 return (o1>t2-eps && o2>t2-eps);
138 bool MEDCouplingDefinitionTimeSlice::isBeforeMe(const MEDCouplingDefinitionTimeSlice *other, double eps) const
140 double t1=getStartTime();
141 double o1=other->getStartTime();
142 double o2=other->getEndTime();
143 return (o1<t1+eps && o2<t1+eps);
146 MEDCouplingDefinitionTimeSliceInst *MEDCouplingDefinitionTimeSliceInst::New(const std::vector<int>& tiI, const std::vector<double>& tiD)
148 MEDCouplingDefinitionTimeSliceInst *ret=new MEDCouplingDefinitionTimeSliceInst;
149 ret->unserialize(tiI,tiD);
153 void MEDCouplingDefinitionTimeSliceInst::getTinySerializationInformation(std::vector<int>& tiI, std::vector<double>& tiD) const
156 tiI[0]=_mesh_id; tiI[1]=_array_id; tiI[2]=_field_id;
161 void MEDCouplingDefinitionTimeSliceInst::unserialize(const std::vector<int>& tiI, const std::vector<double>& tiD)
163 _mesh_id=tiI[0]; _array_id=tiI[1]; _field_id=tiI[2];
167 TypeOfTimeDiscretization MEDCouplingDefinitionTimeSliceInst::getTimeType() const
172 MEDCouplingDefinitionTimeSlice *MEDCouplingDefinitionTimeSliceInst::copy() const
174 return new MEDCouplingDefinitionTimeSliceInst(*this);
177 bool MEDCouplingDefinitionTimeSliceInst::isEqual(const MEDCouplingDefinitionTimeSlice& other, double eps) const
179 if(!MEDCouplingDefinitionTimeSlice::isEqual(other,eps))
181 const MEDCouplingDefinitionTimeSliceInst *otherC=dynamic_cast<const MEDCouplingDefinitionTimeSliceInst *>(&other);
184 return fabs(otherC->_instant-_instant)<eps;
187 void MEDCouplingDefinitionTimeSliceInst::getHotSpotsTime(std::vector<double>& ret) const
193 void MEDCouplingDefinitionTimeSliceInst::getIdsOnTime(double tm, double eps, int& meshId, int& arrId, int& arrIdInField, int& fieldId) const throw(INTERP_KERNEL::Exception)
201 bool MEDCouplingDefinitionTimeSliceInst::isContaining(double tmp, double eps) const
203 return fabs(tmp-_instant)<eps;
206 void MEDCouplingDefinitionTimeSliceInst::appendRepr(std::ostream& stream) const
208 stream << "single point " << _instant;
209 MEDCouplingDefinitionTimeSlice::appendRepr(stream);
212 double MEDCouplingDefinitionTimeSliceInst::getStartTime() const
217 double MEDCouplingDefinitionTimeSliceInst::getEndTime() const
222 MEDCouplingDefinitionTimeSliceInst::MEDCouplingDefinitionTimeSliceInst(const MEDCouplingFieldDouble *f, int meshId, int arrId, int fieldId) throw(INTERP_KERNEL::Exception):MEDCouplingDefinitionTimeSlice(f,meshId,arrId,fieldId)
225 double t1=f->getStartTime(tmp1,tmp2);
226 double t2=f->getEndTime(tmp1,tmp2);
227 double eps=f->getTimeTolerance();
229 throw INTERP_KERNEL::Exception("MEDCouplingDefinitionTimeSliceInst : times differs in this");
233 MEDCouplingDefinitionTimeSliceCstOnTI *MEDCouplingDefinitionTimeSliceCstOnTI::New(const std::vector<int>& tiI, const std::vector<double>& tiD)
235 MEDCouplingDefinitionTimeSliceCstOnTI *ret=new MEDCouplingDefinitionTimeSliceCstOnTI;
236 ret->unserialize(tiI,tiD);
240 MEDCouplingDefinitionTimeSlice *MEDCouplingDefinitionTimeSliceCstOnTI::copy() const
242 return new MEDCouplingDefinitionTimeSliceCstOnTI(*this);
245 bool MEDCouplingDefinitionTimeSliceCstOnTI::isEqual(const MEDCouplingDefinitionTimeSlice& other, double eps) const
247 if(!MEDCouplingDefinitionTimeSlice::isEqual(other,eps))
249 const MEDCouplingDefinitionTimeSliceCstOnTI *otherC=dynamic_cast<const MEDCouplingDefinitionTimeSliceCstOnTI *>(&other);
252 if(fabs(otherC->_start-_start)>eps)
254 return fabs(otherC->_end-_end)<eps;
257 void MEDCouplingDefinitionTimeSliceCstOnTI::getHotSpotsTime(std::vector<double>& ret) const
260 ret[0]=(_start+_end)/2.;
263 void MEDCouplingDefinitionTimeSliceCstOnTI::getIdsOnTime(double tm, double eps, int& meshId, int& arrId, int& arrIdInField, int& fieldId) const throw(INTERP_KERNEL::Exception)
271 bool MEDCouplingDefinitionTimeSliceCstOnTI::isContaining(double tmp, double eps) const
273 return _start-eps<tmp && _end+eps>tmp;
276 void MEDCouplingDefinitionTimeSliceCstOnTI::appendRepr(std::ostream& stream) const
278 stream << "Constant on time interval [" << _start << "," << _end << "]";
279 MEDCouplingDefinitionTimeSlice::appendRepr(stream);
282 double MEDCouplingDefinitionTimeSliceCstOnTI::getStartTime() const
287 double MEDCouplingDefinitionTimeSliceCstOnTI::getEndTime() const
292 void MEDCouplingDefinitionTimeSliceCstOnTI::getTinySerializationInformation(std::vector<int>& tiI, std::vector<double>& tiD) const
295 tiI[0]=_mesh_id; tiI[1]=_array_id; tiI[2]=_field_id;
297 tiD[0]=_start; tiD[1]=_end;
300 void MEDCouplingDefinitionTimeSliceCstOnTI::unserialize(const std::vector<int>& tiI, const std::vector<double>& tiD)
302 _mesh_id=tiI[0]; _array_id=tiI[1]; _field_id=tiI[2];
303 _start=tiD[0]; _end=tiD[1];
306 TypeOfTimeDiscretization MEDCouplingDefinitionTimeSliceCstOnTI::getTimeType() const
308 return CONST_ON_TIME_INTERVAL;
311 MEDCouplingDefinitionTimeSliceCstOnTI::MEDCouplingDefinitionTimeSliceCstOnTI(const MEDCouplingFieldDouble *f, int meshId, int arrId, int fieldId) throw(INTERP_KERNEL::Exception):MEDCouplingDefinitionTimeSlice(f,meshId,arrId,fieldId)
314 double t1=f->getStartTime(tmp1,tmp2);
315 double t2=f->getEndTime(tmp1,tmp2);
320 MEDCouplingDefinitionTimeSliceLT *MEDCouplingDefinitionTimeSliceLT::New(const std::vector<int>& tiI, const std::vector<double>& tiD)
322 MEDCouplingDefinitionTimeSliceLT *ret=new MEDCouplingDefinitionTimeSliceLT;
323 ret->unserialize(tiI,tiD);
327 MEDCouplingDefinitionTimeSlice *MEDCouplingDefinitionTimeSliceLT::copy() const
329 return new MEDCouplingDefinitionTimeSliceLT(*this);
332 bool MEDCouplingDefinitionTimeSliceLT::isEqual(const MEDCouplingDefinitionTimeSlice& other, double eps) const
334 if(!MEDCouplingDefinitionTimeSlice::isEqual(other,eps))
336 const MEDCouplingDefinitionTimeSliceLT *otherC=dynamic_cast<const MEDCouplingDefinitionTimeSliceLT *>(&other);
339 if(_array_id_end!=otherC->_array_id_end)
341 if(fabs(otherC->_start-_start)>eps)
343 return fabs(otherC->_end-_end)<eps;
346 void MEDCouplingDefinitionTimeSliceLT::getHotSpotsTime(std::vector<double>& ret) const
353 void MEDCouplingDefinitionTimeSliceLT::getIdsOnTime(double tm, double eps, int& meshId, int& arrId, int& arrIdInField, int& fieldId) const throw(INTERP_KERNEL::Exception)
355 if(fabs(tm-_start)<eps)
363 if(fabs(tm-_end)<eps)
371 throw INTERP_KERNEL::Exception("LinearTime request not in boundary of this ! use hot spots !");
374 bool MEDCouplingDefinitionTimeSliceLT::isContaining(double tmp, double eps) const
376 return _start-eps<tmp && _end+eps>tmp;
379 void MEDCouplingDefinitionTimeSliceLT::appendRepr(std::ostream& stream) const
381 stream << "Linear on time interval [" << _start << "," << _end << "]";
382 MEDCouplingDefinitionTimeSlice::appendRepr(stream);
383 stream << " EndArrayId : " << _array_id_end;
386 double MEDCouplingDefinitionTimeSliceLT::getStartTime() const
391 double MEDCouplingDefinitionTimeSliceLT::getEndTime() const
396 int MEDCouplingDefinitionTimeSliceLT::getEndId() const
398 return _array_id_end;
401 void MEDCouplingDefinitionTimeSliceLT::getTinySerializationInformation(std::vector<int>& tiI, std::vector<double>& tiD) const
404 tiI[0]=_mesh_id; tiI[1]=_array_id; tiI[2]=_field_id; tiI[3]=_array_id_end;
406 tiD[0]=_start; tiD[1]=_end;
409 void MEDCouplingDefinitionTimeSliceLT::unserialize(const std::vector<int>& tiI, const std::vector<double>& tiD)
411 _mesh_id=tiI[0]; _array_id=tiI[1]; _field_id=tiI[2]; _array_id_end=tiI[3];
412 _start=tiD[0]; _end=tiD[1];
415 TypeOfTimeDiscretization MEDCouplingDefinitionTimeSliceLT::getTimeType() const
420 MEDCouplingDefinitionTimeSliceLT::MEDCouplingDefinitionTimeSliceLT(const MEDCouplingFieldDouble *f, int meshId, int arrId, int arr2Id, int fieldId) throw(INTERP_KERNEL::Exception):MEDCouplingDefinitionTimeSlice(f,meshId,arrId,fieldId),_array_id_end(arr2Id)
423 double t1=f->getStartTime(tmp1,tmp2);
424 double t2=f->getEndTime(tmp1,tmp2);
429 MEDCouplingDefinitionTime::MEDCouplingDefinitionTime():_eps(EPS_DFT)
433 MEDCouplingDefinitionTime::MEDCouplingDefinitionTime(const std::vector<const MEDCouplingFieldDouble *>& fs, const std::vector<int>& meshRefs, const std::vector<std::vector<int> >& arrRefs) throw(INTERP_KERNEL::Exception)
435 std::size_t sz=fs.size();
436 if(sz!=arrRefs.size())
437 throw INTERP_KERNEL::Exception("MEDCouplingDefinitionTime constructor : internal error ! should never happen !");
439 for(std::size_t i=0;i<sz;i++)
442 throw INTERP_KERNEL::Exception("MEDCouplingDefinitionTime constructor : A field is null in list impossible to build a time definition !");
443 _slices[i]=MEDCouplingDefinitionTimeSlice::New(fs[i],meshRefs[i],arrRefs[i],(int)i);
447 const MEDCouplingDefinitionTimeSlice *ref=_slices[0];
448 _eps=fs[0]->getTimeTolerance();
449 for(std::size_t i=1;i<sz;i++)
451 if(!ref->isAfterMe(_slices[i],_eps))
452 throw INTERP_KERNEL::Exception("MEDCouplingDefinitionTime constructors : the sequences of fields does NOT defines a stricly ascendant monotonic time sequence !");
453 // double t1=ref->getEndTime();
454 // double t2=_slices[i]->getStartTime();
455 // if(fabs(t1-t2)<_eps)
456 // if(ref->getEndId() != _slices[i]->getStartId())
457 // throw INTERP_KERNEL::Exception("MEDCouplingDefinitionTime constructor : 2 slices refers to the same time and underlying arrays differs !");
462 void MEDCouplingDefinitionTime::assign(const MEDCouplingDefinitionTime& other)
464 std::size_t sz=other._slices.size();
466 for(std::size_t i=0;i<sz;i++)
467 _slices[i]=other._slices[i]->copy();
470 bool MEDCouplingDefinitionTime::isEqual(const MEDCouplingDefinitionTime& other) const
472 std::size_t sz=_slices.size();
473 if(sz!=other._slices.size())
475 for(std::size_t i=0;i<sz;i++)
476 if(!_slices[i]->isEqual(*other._slices[i],_eps))
481 void MEDCouplingDefinitionTime::getIdsOnTimeRight(double tm, int& meshId, int& arrId, int& arrIdInField, int& fieldId) const throw(INTERP_KERNEL::Exception)
483 std::vector<int> meshIds;
484 std::vector<int> arrIds;
485 std::vector<int> arrIdsInField;
486 std::vector<int> fieldIds;
487 getIdsOnTime(tm,meshIds,arrIds,arrIdsInField,fieldIds);
488 meshId=meshIds.back();
490 arrIdInField=arrIdsInField.back();
491 fieldId=fieldIds.back();
494 void MEDCouplingDefinitionTime::getIdsOnTimeLeft(double tm, int& meshId, int& arrId, int& arrIdInField, int& fieldId) const throw(INTERP_KERNEL::Exception)
496 std::vector<int> meshIds;
497 std::vector<int> arrIds;
498 std::vector<int> arrIdsInField;
499 std::vector<int> fieldIds;
500 getIdsOnTime(tm,meshIds,arrIds,arrIdsInField,fieldIds);
501 meshId=meshIds.front();
502 arrId=arrIds.front();
503 arrIdInField=arrIdsInField.front();
504 fieldId=fieldIds.front();
507 void MEDCouplingDefinitionTime::getIdsOnTime(double tm, std::vector<int>& meshIds, std::vector<int>& arrIds, std::vector<int>& arrIdsInField, std::vector<int>& fieldIds) const throw(INTERP_KERNEL::Exception)
509 std::vector<int> ids;
511 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingDefinitionTimeSlice> >::const_iterator it=_slices.begin();it!=_slices.end();it++,id++)
512 if((*it)->isContaining(tm,_eps))
515 throw INTERP_KERNEL::Exception("MEDCouplingDefinitionTime::getIdsOnTime : No matching slice for such time !");
516 std::size_t sz=ids.size();
518 throw INTERP_KERNEL::Exception("MEDCouplingDefinitionTime::getIdsOnTime : Too many slices match this time !");
522 arrIdsInField.resize(sz);
524 for(std::size_t i=0;i<sz;i++)
525 _slices[ids[i]]->getIdsOnTime(tm,_eps,meshIds[i],arrIds[i],arrIdsInField[i],fieldIds[i]);
528 std::vector<double> MEDCouplingDefinitionTime::getHotSpotsTime() const
530 std::vector<double> ret;
531 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingDefinitionTimeSlice> >::const_iterator it=_slices.begin();it!=_slices.end();it++)
533 std::vector<double> tmp;
534 (*it)->getHotSpotsTime(tmp);
537 if(fabs(ret.back()-tmp.front())>_eps)
538 ret.insert(ret.end(),tmp.begin(),tmp.end());
540 ret.insert(ret.end(),tmp.begin()+1,tmp.end());
543 ret.insert(ret.end(),tmp.begin(),tmp.end());
548 void MEDCouplingDefinitionTime::appendRepr(std::ostream& stream) const
550 stream << "Time definition :\n";
551 for(std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingDefinitionTimeSlice> >::const_iterator it=_slices.begin();it!=_slices.end();it++)
554 (*it)->appendRepr(stream);
559 void MEDCouplingDefinitionTime::getTinySerializationInformation(std::vector<int>& tinyInfoI, std::vector<double>& tinyInfoD) const
561 int sz=(int)_slices.size();
564 tinyInfoI.resize(3*sz+2);
566 std::vector<int> coreData;
567 for(int i=0;i<sz;i++)
569 std::vector<int> tmp1;
570 std::vector<double> tmp2;
571 tinyInfoI[i+2]=(int)_slices[i]->getTimeType();
572 _slices[i]->getTinySerializationInformation(tmp1,tmp2);
573 tinyInfoI[i+sz+2]=(int)tmp1.size();
574 tinyInfoI[i+2*sz+2]=(int)tmp2.size();
575 coreData.insert(coreData.end(),tmp1.begin(),tmp1.end());
576 tinyInfoD.insert(tinyInfoD.end(),tmp2.begin(),tmp2.end());
578 tinyInfoI[1]=(int)coreData.size();
579 tinyInfoI.insert(tinyInfoI.end(),coreData.begin(),coreData.end());
582 void MEDCouplingDefinitionTime::unserialize(const std::vector<int>& tinyInfoI, const std::vector<double>& tinyInfoD)
589 for(int i=0;i<sz;i++)
591 TypeOfTimeDiscretization ty=(TypeOfTimeDiscretization) tinyInfoI[i+2];
592 int sz1=tinyInfoI[i+sz+2];
593 int sz2=tinyInfoI[i+2*sz+2];
594 std::vector<int> tmp1(tinyInfoI.begin()+3*sz+2+offset1,tinyInfoI.begin()+3*sz+2+offset1+sz1);
595 std::vector<double> tmp2(tinyInfoD.begin()+offset2,tinyInfoD.begin()+offset2+sz2);
596 MEDCouplingDefinitionTimeSlice *pt=MEDCouplingDefinitionTimeSlice::New(ty,tmp1,tmp2);